The issue with "repeat with … in ..." loop

I know this issue has been discussed several times. But I’m still not sure I understand what it’s all about.

By way of example:

tell app "Adobe InDesign 2024"
tell document 1

repeat with layerName in listOfLayerNames 

    set visible of layer layerName to true

end repeat

end tell
end tell

This suddenly causes this error to a user:

Adobe InDesign 2024 got an error: Can’t set visible of layer (item 7 of {"NY", "OTS", "BR", "IT", "MV", "MWS", "xxx", "xrt"}) of document "0211_xxx_xxx_xx1.indd" to true.

The strange things about this error are the following:

-I can never reproduce it.
-Users who report such errors once in a while also can’t consistently reproduce it. It just happens at random (and quite rarely).

This did happen before with other similar loops and I do know how to fix it:

repeat with layerNum from 1 to (count listOfLayerNames) 
    set layerName to (item layerNum of listOfLayerNames) as string

Then the loop always works.

I know that it was recommended on the forum to use “contents of <variable>”. I don’t want to use it in InDesign to avoid conflicts with InDesign’s own “contents” property.

So is it just a bug in AppleScript? And we should just give up the convenient fast enumeration repeat with ... in ... entirely? Or am I missing something?

No, it’s not.

layerName in repeat with layerName in listOfLayerNames is a reference to the element in the list, you can see it in the error message: (item 7 of {"NY", "OTS", "BR", "IT", "MV", "MWS"}).

The recommendation contents of is the only way to dereference the object.

As contents of is applied directly to the reference it’s unlikely that it causes a terminology clash.

Note that the error occurs only when the item is going to be modified. AppleScript dereferences the object implicitly when it’s only read.

StefanK is correct.
So your script above would only need one line added like so…

tell app "Adobe InDesign 2024"
	tell document 1
		repeat with layerName in listOfLayerNames 
			set layerName to contents of layerName
    		set visible of layer layerName to true
		end repeat
	end tell
end tell

I have the same problem with devonthink, which also has a contents property.

That aside, why would the repeat loop ask for a seventh item in a list of only six? Assuming that there isn’t intervening code that changes the value of the listOfLayerNames list, wouldn’t that inherently a bug, albeit it within indesign?

oops I just shortened the list for brevity sake without realizing I only left 6 items. I added 2 more items now to the original post to avoid confusion.

1 Like

Thanks for the insight!

But the question still remains: why there’s no consistency in the way it works?

From my experience, the

repeat with var in list
code works as is in some 95% of execution instances.

Then the same code gives the aforementioned error out of the blue when doing exactly the same thing it did before many times.

The user that reported this error ran the same code without issues many times before.

Like I mentioned, it’s not the first time it happened. Once in a while users suddenly report this error, which makes me change yet another loop into repeat with n from 1 to...

And also make another mental note to just never use fast enumeration in the future to avoid this hassle again (which I don’t always follow - and then fall into the same trap again haha).

In my view, this loop should work consistently either this way or that way. But not throwing unexpected errors on a whim.

That’s why I’m inclined to think there is a bug somewhere there in the way AppleScript executes this loop.

Actually the loop works consistently if you follow these rules.

• If you perform an equality check or you are going to write into var you must dereference the item with contents of
• If you just read var AppleScript dereferences the value on your behalf.

I’ve encountered this behavior several times when scripting InDesign.
But as you said, it’s impossible to reproduce it on purpose.
Don’t worry: you can use contents of without problem as long as the command doesn’t involve text.
In your specific case, you can also try this:
`set visible of layer (layerName as string) to true

Just out of curiosity, where do you trigger the script from? InDesign palette, FastScript?
And is your script embedded in a “do script” block?

Thanks to everyone who replied!

Now I have a clear idea regarding the behavior of this loop (well it only took 20 years).

Well my complaint is not that it works under the aforementioned conditions. The problem is that the the loop also works when you don’t use contents of while modifying the variable.

That’s where inconsistency is. Like I mentioned, the loop I posted that now gave this one-off error to one user, worked as is for years and years for many users - and is still working. Just like many similar loops in other places that never caused any issues so far.

If this loop isn’t supposed to work without contents of, then it should never work and should always return an error (preferably with a human-readable suggestion how to rectify the error).

That’s why I still consider it a bug. The bug is that the loop works when it’s not supposed to - until it’s suddenly doesn’t work for no apparent reason.

Regardless, now thanks to your and other posters’ suggestion, I now know how to build this loop in a reliable way. To me it’s repeat with n in (count list) as this one doesn’t seem to contain any hidden surprises no matter where and how I use it.

From my experience with InDesign, it’s to finicky to risk any potential clash of terminology. It may work with no issues for years until it’s suddenly doesn’t work after an update of InDesign or/and macOS.

I also did try (var as string) in the past and I think at one point it also gave me an error like can't convert classNameHere (item 7 of {list}) into type string. I can’t vouch that that was the error all I recall is that I had to abandon this approach, too.

Like I mentioned, it looks to me that repeat with n in (count list) is the safest bet for this loop.

Thanks again for suggesting the solutions!

Also, when I first learned about the contents of approach (not too long ago), I thought it’s some kind of an ingenious trick invented by AppleScript gurus.

Now after I dug deeper, I found out that it’s actually documented (to my surprise):

Even if buried deep in the jungle of documentation archive.

One should be curious and patient enough to fully explore this Note from the current scripting guide:

When I started learning AppleScript some 20 years ago - largely from code examples and tutorials posted by experienced scripters - I’m pretty sure that contents of wasn’t really used anywhere. Otherwise I would’ve picked up on this! Well the code worked anyway. Interesting stuff.

About 20 years ago Matt Neuburg released his book “AppleScript The Definitive Guide”. There are two sections “Dereferencing a Reference” (p. 213) and “Trouble with Contents” (p. 216) which cover the issue :wink:

yeah i didn’t read no books back then

1 Like