Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Infinite Loop Detected

This happens 3-5x per hour. Can anyone shed some light based on my scripts? (Search is currently disabled.)  
1555040822
The Aaron
Roll20 Production Team
API Scripter
I can't imagine which script would be causing that issue.  I have (and wrote) all those scripts except for SimpleDoorControls.js, and I don't get an infinite loop error with them.  I'd suggest disabling that one and seeing if you get the issue.
1555040952
The Aaron
Roll20 Production Team
API Scripter
Are you using this one?&nbsp;&nbsp;<a href="https://app.roll20.net/forum/permalink/1577941/" rel="nofollow">https://app.roll20.net/forum/permalink/1577941/</a>
1555044916

Edited 1555044990
I have pasted the entire script here, which, honestly, I know nothing about. All of my experience with these scripts and macros is taking things I've found on the forums and changing just enough of them to make it roll the dice we need without breaking the thing. /* SimpleDoorControls Use Creating a linked door system ----------------------------- Verify you're on the Token/Object Layer. Place a graphic of a door or other barrier in the closed position. Name that token DoorClosed (all one word, and yes the D and C need to be capitalized). Place a graphic of a door in the desired open position. Name that token DoorOpen (all one word, and yes the D and O need to be capitalized). Draw a line to act as the Dynamic Lighting barrier for the door when closed (while still on the Token layer). Select all three objects. Type !DoorsLink (or set it as a macro and use that macro) The Open Door and Dynamic Lighting barrier will be moved to the GM layer and Dynamic Lighting layer, respectively. The open and closed doors will be renamed.&nbsp; This is how they are linked. DO NOT RENAME THE LINKED OBJECTS. Do this for each set of doors needed. Opening and Closing doors ------------------------- Once the objects are linked Select the door on the token layer Type !DoorOpenClose The door will open if it is closed, or it will close if it is opened. */ on("chat:message", function (msg) { &nbsp; &nbsp; "use strict"; &nbsp; &nbsp; var Parts = {}; &nbsp; &nbsp; if (msg.type !== "api") { &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; switch(msg.content.split(/\s+/).shift()) { &nbsp; &nbsp; &nbsp; &nbsp; case "!DoorsLink": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //make sure three items are selected &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (msg.selected.length &gt; 3) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("Doors", "/w gm You have selected too many things, looking among them for what I need."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (msg.selected.length &lt; 3) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("Doors", "/w gm You have not selected enough things."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //identify and get the ID for each each type of selected item &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each(msg.selected, function(obj) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var o = getObj(obj._type, obj._id); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(o) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (o.get("_type") === "graphic" &amp;&amp; o.get("name") === "DoorOpen" &amp;&amp; !Parts.DoorOpen) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parts.DoorOpen=o; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (o.get("type") === "graphic" &amp;&amp; o.get("name") === "DoorClosed" &amp;&amp; !Parts.DoorClosed) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parts.DoorClosed = o; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (o.get("type") === "path" &amp;&amp; !Parts.Path) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parts.Path = o; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( Parts.DoorOpen &amp;&amp; Parts.DoorClosed &amp;&amp; Parts.Path) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parts.DoorOpen.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: Parts.Path.id +" "+Parts.DoorClosed.id, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: "gmlayer" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parts.DoorClosed.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: Parts.Path.id +" "+Parts.DoorOpen.id &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Parts.Path.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: "walls" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("Doors", "/w GM Couldn't fine required piece:&lt;ul&gt;" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +(Parts.DoorOpen ? '' : '&lt;li&gt;Token named "DoorOpen".&lt;/li&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +(Parts.DoorClosed ? '' : '&lt;li&gt;Token named "DoorClosed".&lt;/li&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +(Parts.Path ? '' : '&lt;li&gt;Path for Dynamic Light Layer.&lt;/li&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/ul&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; case "!DoorOpenClose": &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.chain(msg.selected) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(function(o){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return getObj('graphic', o._id); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reject(_.isUndefined) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(function(o){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 'objects' === o.get('layer'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .each(function(o){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var params=o.get('name').split(/\s+/), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oDoor = getObj('graphic',params[1]), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oPath = getObj('path',params[0]); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(oDoor &amp;&amp; oPath) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; o.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: 'gmlayer' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oDoor.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: 'objects' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; oPath.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: ( 'walls' === oPath.get('layer') ? 'gmlayer' : 'walls') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('Doors','/w gm Missing components: &lt;ul&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +(oDoor ? '' : '&lt;li&gt;GM Layer Door&lt;/li&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +(oPath ? '' : '&lt;li&gt;Dynamic Lighting Path&lt;/li&gt;') &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; +'&lt;/ul&gt;'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; } });
Dang. Same error just now, with Search and SimpleDoorControls.js both disabled.
1555073374
The Aaron
Roll20 Production Team
API Scripter
Oh! &nbsp;What character sheet are you using? &nbsp;Character sheet’s Sheet Worker code is also run by the API.&nbsp;
I'm using the stock Roll20 sheet on all my campaigns.
1555084188
The Aaron
Roll20 Production Team
API Scripter
When did the infinite loops start happening?
I've had them occasionally for about 6 months I'd say. I notice that it has happened when I am using my macros for TokenMod and they stop working. TokenMod I use every day in every game I run for the last year or so. Message of the Day obviously just sits there doing it's thing every day. Had that for about a year. SimpleDoorControls I haven't made hardly any use of, but I've had it for about 6 months or so. Search was a new pick up last month and I don't think we've gotten much use out of it. I got it for my players mostly. TokenNameNumber is a new pick up last month too, and I've only just started using it this week in earnest. I"m also using VTT Enhancement Suite, not sure if that is related or not. <a href="https://chrome.google.com/webstore/detail/vtt-enhancement-suite/fadcomaehamhdhekodcpiglabcjkepff" rel="nofollow">https://chrome.google.com/webstore/detail/vtt-enhancement-suite/fadcomaehamhdhekodcpiglabcjkepff</a>
1555088169
The Aaron
Roll20 Production Team
API Scripter
That extension won't have any bearing on the API.&nbsp; Has it always been 3-5x per hour, or is that a recent development?
That's a good question, I'm noticing it this week since I have been overhauling my monster manual in preparation for making a campaign to transfer all of my monsters into for storage and transmog from one spot in the future. Since I'm spending a lot of time in and out of the tokens and monster sheets, I'm using my tokenmod controls constantly to set the token parameters and I notice almost immediately when the API shuts down, so I'm restarting it manually right away. So it could be that I'm just now noticing how often it is because of how often I am starting it up right now.
Possibly worth noting - while I had been working all week on my Rise of Tiamat campaign, today I am working on my Storm King's Thunder campaign, and I'm having the same issue, with the same API scripts installed.
1555090085
The Aaron
Roll20 Production Team
API Scripter
Does it only seem to happen when you use TokenMod commands?&nbsp; Can you narrow it down to a few commands that seem to cause it?&nbsp; Maybe post them here?
I couldn't say it only seems to happen for TokenMod commands, but those are the ones that are actively used, so I notice when they fail. These are the 2 macros I'm using most often. The first one I have used a ton in the past two days, when I've noticed this issue constantly. I create monsters by dragging them from the SRD or from scratch if need be. Then I upload my token .PNG directly into the NPC sheet and save it. Drag the token out of the journal onto the table top, select it and press this macro: !token-mod --set bar1_link|hp !token-mod --set bar1_reset| !token-mod --set bar2_link|npc_ac !token-mod --set bar1_link| !token-mod --off light_hassight !token-mod --set light_radius|=0 light_dimradius|0 !token-mod --off light_otherplayers !token-mod --on showname !token-mod --on showplayers_name !token-mod --set defaulttoken This makes tokens "dead". I often notice that the API has crashed during a game session when I try to use this macro and it fails. !token-mod --set statusmarkers|=dead !token-mod --off showname !token-mod --set bar1|0
1555128576
The Aaron
Roll20 Production Team
API Scripter
Try specifying those all as a single command. By having that as 10 separate commands, it puts a ton of load on the event system. You can span multiple lines with {{ }} to keep the formatting nice.&nbsp;
OK I understand what you're saying, but I can't seem to nail down the syntax. Can you give me an example?
1555166880
GiGs
Pro
Sheet Author
API Scripter
Your top command would look like !token-mod {{ &nbsp;&nbsp;&nbsp;&nbsp;--set &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar1_link|hp &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar1_reset| &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar2_link|npc_ac &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bar1_link| &nbsp;&nbsp;&nbsp;&nbsp;--off light_hassight &nbsp;&nbsp;&nbsp;&nbsp;--set light_radius|=0 light_dimradius|0 &nbsp;&nbsp;&nbsp;&nbsp;--off light_otherplayers &nbsp;&nbsp;&nbsp;&nbsp;--on &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showname &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;showplayers_name &nbsp;&nbsp;&nbsp;&nbsp;--set defaulttoken }} You can probably shift them around a bit too for neatness, getting all the sets together and all the offs together.
1555167041
GiGs
Pro
Sheet Author
API Scripter
I'm curious about this line --set light_radius|=0 light_dimradius|0 I dont use dynamic lighting, so I dont use these commands. Is there a difference between |=0 &nbsp;for light_radius, and |0 &nbsp;for dimradius?
1555170159

Edited 1555170194
The Aaron
Roll20 Production Team
API Scripter
That's part of TokenMod. = is the default operation if one isn't specified.&nbsp; You only really need to specify it when you want to explicitly assign a negative value: !token-mod --set light_radius|=-5 !token-mod --set light_radius|-5 The first sets the light_radius to -5, the second deducts 5 from the current value and sets it to the resultant value.
Wow, OK, this may have resolved my Infinite Loop issue. I haven't had it happen since yesterday morning I think. I am having an issue where the macro isn't setting the hit points. After clicking the macro all of the other operations have completed, but Bar 1 is set to NONE and there are no values at all in the Bar 1 boxes.&nbsp; !token-mod {{ --set bar1_link|hp bar1_reset| bar2_link|npc_ac bar1_link| --off light_hassight --set light_radius|=0 light_dimradius|0 --off light_otherplayers --on showname showplayers_name showplayers_bar1 --set defaulttoken }}
1555270642
GiGs
Pro
Sheet Author
API Scripter
swap the order of bar1_reset is after bar1_link|hp, and after that you have bar1_link| I know thats the order i gave earlier, but i was just copying your earlier commands. So it should probably be !token-mod {{ --set bar1_reset| bar1_link|hp bar2_link|npc_ac --off light_hassight --set light_radius|=0 light_dimradius|0 --off light_otherplayers --on showname showplayers_name showplayers_bar1 --set defaulttoken }} Maybe bar1_reset isnt needed? Or maybe you should have a bar2_reset there too (before its link).
Maybe Aaron can confirm/deny, but this is my understanding of these commands: bar1_link|hp bar1_reset| bar2_link|npc_ac bar1_link| In this example, let assume the character sheet has 60 hp. 1) Bar 1 is linked to HP, and the result is 0/60. 2) Bar 1 is reset to maximum value, and the result is 60/60 3) Bar 2 is linked to the NPC_AC value (this is working fine) 4) Bar 1 is UNlinked to any value (the purpose in this case is make this token a mook - ie it's a goblin and I'm going to need more than 1 linked to this sheet.
1555271909
GiGs
Pro
Sheet Author
API Scripter
ah yes, that makes sense. I havent used TokenMod in a while.
1555324718

Edited 1555324750
The Aaron
Roll20 Production Team
API Scripter
1) will set link it to HP and set the value to @{hp}/@{hp|max}.&nbsp; 2) will set bar1_current to bar1_max.&nbsp; You should’ve need 2) in this case. It is failing because all the changes are applied as one set operation for efficiency, so the state of bar1_max is read from the beginning state of the token, not the state after the link operation. I can probably fix it to look at the updated state if you find it isn’t right without it.&nbsp;
So.. this version is working, but only if I press it twice. The first press ignores the bar1_reset| command, or at least, it doesn't set it to max value of the character sheet's hp. I'm really just trial-and-error mashing these commands together, with no sense of what is going to happen until I try it. !token-mod {{ --set bar1_link|hp bar1_reset| light_radius|=0 light_dimradius|0 bar2_link|npc_ac --off light_hassight light_otherplayers --on showname showplayers_name showplayers_bar1 }} !token-mod {{ --set bar1_link| defaulttoken }}
1555415322
The Aaron
Roll20 Production Team
API Scripter
Hmm. I’ll have to test that. Is your use case calling it on a single token?
It works the same on 1 token or multiple at the same time. (I've done 3 at a time to test it)
Knock on wood, but I will say that I haven't seen the Infinite Loop error since Saturday. It's just that the macro doesn't work as well, but it is adequate and it saves me a ton of time as I set up my personal monster manual.