New Script: Same Table Linked Records Backlinks

Topic Labels: Scripting extentions
15849 64
Showing results for 
Search instead for 
Did you mean: 
10 - Mercury
10 - Mercury

Explainer Video:



64 Replies 64

Took another look at that error, it seems like your loop isn’t terminating correctly, try changing line 116 to


otherwise, on its last check, the code goes

  • foundItem.length is 0 - true
  • let’s go splice our obviously empty array
  • uh, oh, something went wrong, boss

Using the length instead of a direct check for the loop is a smart move, mind you, because it’s way faster than accessing the whole Object directly and it’s likely that the code will re-evaluate line 116 a bunch of times so the performance gain could be significant, depending on the base. The drawback here was a bit of a loss on the readability front but hopefully this gets it working.

Thanks. I’ve tried changing line 116. I get the following error:

SyntaxError: Unexpected token ‘}’
on line 1
at a on line 1
at Generator._invoke on line 1
at Generator.F.forEach.u. [as next] on line 1
at u on line 1
at o on line 1
on line 1
on line 1

Which makes me think there is a bracket out of place, but I’m not sure where that bracket is.

Could you share a screenshot of the change that you made to line 116, including as much of the code that follows it as possible?

Thanks! Here is a screenshot.

Screen Shot 2021-07-07 at 7.15.50 PM
I re-added the code so line 116 is now line 120.

Let me know if there is anything else that would be helpful to share.

I think that there may be some confusion here. There have been multiple scripts shared in this thread, and the tip from @Dominik_Bosnjak is related to line 116 in the latter of the two—the post by @Theo_Michel in September of 2020—which looks like this:

    if(foundItem >= 0) {

The script snippet in the screenshot that you shared didn’t come from that script, so the change that you made actually introduces a bug because it’s not related to the rest of the code.

Which script above did you use as the basis for your setup?

Thanks. I was not aware there were two scripts on the page. I am using the script at the top of the page.

Do you think it would be better to use the 2nd one?

Could you clarify the difference between the two?

Wow, good call @Justin_Barrett , I was debugging the wrong thing weeks apart.

I’ll take another look in a bit, but as far as merit goes, the second script utilizes recursion, takes advantage of prototypal inheritance, and is nicely formatted to top it off so that I can actually see what’s going on even through a Friday migraine.

Basically, some of JavaScript’s biggest strengths utilized in 130 lines of code.

The other effort, the one you’re trying to get to work, apparently, is tenacious, but clearly written by someone less experienced; possibly someone who only picked up programming with JavaScript. Just my 2 cents on

How often do you need this to run? And are you sure you want it to be an automation? A base with a couple thousand records in it and you’re one missing semicolon away from filling your monthly automation quota within hours. Unless you’re only running a single automation per base and that sole isn’t in charge of both creation and deletion, that 100k cap is never too safe.

And you know, we had a lot of missing semicolons here by now haha.

huh… A Masters in Computer Science, 20+ years of professional programming across atleast 5 different languages, built systems supporting millions of users, built one of the more popular Airtable products in their ecosystem, and still have a long ways to go to catch up to your skills. Thanks for keeping me humble Dominik, I always need the reminder :winking_face:

Nah, we’re about even if I also count my years of experience in eating my own words, that “I’m an idiot” feeling is quintessential programming imo, more than any technology or trend can ever hope to be. And I’m yet to encounter someone who codes – maybe for a living, maybe just because, emphasis on the present tense – and is in need of a humbling haha.

Case in point: you not automatically assuming I meant the other person because my comment doesn’t make sense otherwise.

Whereas in reality, it’s just an indexing issue . :joy:

And if Theo(dore?) frequents these forums, I’m now really curious how accurate I’ve been overall.

Scripting has undergone a lot of changes since this thread was started.

I decided to write a new version of the script to take advantage of some new features, such as script settings, that lets the script remember the table and fields without having to touch the code.

This version has a few differences from the original and is entirely my own code, although aspects of the algorithm are similar.

  • uses script settings for setting table & fields (which did not exist before)
  • works on only one table, not multiple tables
  • does not allow limiting records to a view
  • various speed improvements and error checking

This script is best used as a batch update when first setting up back links. I also have a matching automation script for when either the link or the backlink is updated, without needing to store previous versions of links. If you are interested in the automation script, please book an appointment with me.

Could you please point out where the recursion and inheritance occur?
I’m not seeing either.

I also find a few things in the script to be rather curious, such as line 67:

if(!currentAddedKidParents.includes( { id:, name: })) {

I bet this line does not do what the author intended. This condition will always evaluate as true. When using .includes() with an array of objects, JavaScript checks if the objects themselves are included, not the contents of the object. As written, the newly created object will never be included in the array, even if the array has an object with the same property values. Thus the includes() will always be false, and the ! negates that , making the condition always true.

There are a few other things in the script that imply that the author had limited experience with Airtable scripting when he wrote the script. For example, every pair of updateRecordAsync calls could be condensed into a single call, which would cut the run time almost in half. (And there are several other changes that could speed up the script, such as not having updateRecordAsync inside a loop.)

Could you please point out where the recursion and inheritance occur?
I’m not seeing either.

Sure, I haven’t been wrong all day, got to start somewhere :grinning_face_with_sweat: : is the findChildren function not both recursive and prototypal in places? The latter because it implicitly inherits the getRecord method and just rolls with it?

The former because of the way it creates its tree object, for example? Its async sync queue trigger is kind of recursive as well, it has a single stop/start condition and the interpreter is left to figure out the best ratios. This all comes together to form a solution that should work in any base, regardless of size, as syncing part keeps it keeps reusing its few functions for roughly (records.length/50)+1 cycles. or other properties - assuming the initial setup was correct.

Basically, it should work in any base, regardless of size and other properties, because it keeps switching between filling the queue and clearing it, for as long as needed.

Why do I have a feeling I’m flunking math and just how many scripts have been posted so far, I can’t even find that line 67. The thing I’m looking at and was looking at originally is a gist, I’m leaving just the canonical url here because some filter keeps complaining about repost attempts:


And my original point was that this was good, not that the other thing was bad.

Maybe we’re talkin about different scripts here.

I was replying to this part of your post …

I thought your comments above were referring to the second script (theomichel/backlinks.js) because it has exactly 130 lines of code.

This script does not include the findChildren function. I also do not see any recursion or prototypical inheritance in this script.

On the other hand, the first script (on2air/same-table-backlinks.js) has 147 lines of code, and does include the findChildren function.

The findChildren function is not recursive. It does not call itself. Only syncLinks calls findChildren.

Thank you for pointing out this example of what you meant by prototypical inheritance. I was looking for something else, not a case of an object from the api using a method defined in the api.

Both scripts should work in any base of any size. (My script does as well.)

This is why I was looking for those features in the script. Both scripts have their merits, and both scripts have things that could be cleaned up.

I think the main concept missing when comparing the two scripts is that they serve different purposes.

  • One script is meant to be run manually to create backlinks in bulk, and requires only two linked same-table link fields.
  • The other script is meant to be run as an automation to maintain a system of same-table links that actually requires four same-table link fields.

My automation script for maintaining same-table backlinks is now available on my Gumroad store.

This is great @kuovonne, we need this (for parent / child relationships) but we also need one for sibling relationships… i.e. only one linked field with multiple entries.


Running the script on:
Name Siblings
1 2,3

Should lead to:

Name Siblings
1 2,3
2 1,3
3 1,2

Is this possible? Or is there a workaround?

I’ve tried achieving this with automations, breaking out sibling IDs as separate formula fields and using lookups to create the updates… however this creates a recursive loop which I can’t seem to stop.

Help would be greatly appreciated!

It is possible to have a script to update sibling relationships. There are two potential scripts: a button script for establishing siblings relationships for existing records, and an automation script for maintaining sibling relationships on an ongoing basis. An automation script can include logic to avoid the recursive loop of unending automation runs. Please let me know if you are interested in hiring me to write these scripts.

However, usually sibling relationships are managed through a parent record. All of the siblings are linked to the same parent. The parent rolls up information about all the children/siblings, and then another rollup field passes the necessary information back down to all the children/siblings.

Hi @kuovonne thanks for offering your help. Yes, I’d appreciate your help with this. I’ve explored a parent record approach, but this seems more clunky. Since our focus is on each individual client, it’s best to know specifically who their family members / relationships are (spouse, children, parents, siblings, in-laws, extended family).

I’ve already used your script for spouse / children. Thanks for posting that.

How can we liaise with you to get you to write an automation(s) for siblings, in-laws and extended family in our contacts table?

@Tristan_Scifo You can book an appointment with me to discuss your needs. I use a booking calendar with a rolling two week basis, so I currently have only a few appointment slots available, but appointments on future days will open up as they come in the two week window.

It sounds like the same-table backlinks scripts works for parents/children, and spouses. Scripts for sibling same-table links is also doable. However, dealing with in-laws, extended family, and other blended family relationships can be0 tricky. For example, when adding a child to one spouse, should that child become a child of the other spouse and siblings of the other spouse’s children? These complex relationships might be more than you want to handle automatically.

We have an automatic linking feature - Same Table Linked Records plus 60+ more Airtable functions in the On2Air Actions app.

Here’s a tutorial:

Hannah - - Automated Backups for Airtable
5 - Automation Enthusiast
5 - Automation Enthusiast

This is super helpful. Works like a charm. Thank you.