createMoveItemAction fails with "Error: The script object is no longer valid."

After a few weeks focusing on something else, I got back to UXP coding and some code does not seem to work anymore.
I upgraded ppro version a few times in between, not sure if this is a regression (or if it was not working - but not tested yet - back then )

 await project.lockedAccess(async () => {
  const result = project.executeTransaction(async (compoundAction) => {
    for(let i = 0; i < sequenceArray.length; i++) {
      try {
        const sequence = sequenceArray[i];
        const projItem = await sequence.getProjectItem();
        const action = await rootItem.createMoveItemAction(projItem, folderItemTarget);
        allActions.push(action);
      } catch(e) {
        logException(e);
      }
      for(let i = 0; i< allActions.length; i++)
      {
        compoundAction.addAction(allActions[i]);
      }
    }
  )
 }

Error: The script object is no longer valid.
at moveAllSequencesToBin (main.js:1815:37)
at async websocket.onmessage (main.js:2780:9)

Flow:

  1. User pick a folder item, the code retrieved the selected item and cast it as a FolderItem then cache it in a variable.
  2. User press OK, this open a websocket to a local http server that process some stuff
  3. When remote processing is done (the websocket.onMessage callback in the plugin it called), some sequences are added to the project (via code)
  4. Those newly created sequence are then moved to the previously cached FolderItem (code snippet above)

Is it possible that adding Sequence to the project (step #3 above) invalidates the folderItem object that was cached (despite the two being unrelated) ?
Bug ?

Hello,

The issue that you are running into with your snippet is that the callbacks to project.lockedAccess() and project.executeTransaction()must be synchronous.

To accomplish the flow that you’ve described your snippet would have to be modified into something like this:

// resolve all async data before entering the transaction
const projItems = [];
for (let i = 0; i < sequenceArray.length; i++) {
    try {
        const projItem = await sequenceArray[i].getProjectItem();
        projItems.push(projItem);
    } catch (e) {
        logException(e);
    }
}

// build and commit all actions synchronously inside the lock
project.lockedAccess(() => {                           
    project.executeTransaction((compoundAction) => {           
        for (let i = 0; i < projItems.length; i++) {
            try {
                // createMoveItemAction is synchronous: no await needed
                const action = rootItem.createMoveItemAction(projItems[i], folderItemTarget);
                if (action) {
                    compoundAction.addAction(action);
                }
            } catch (e) {
                logException(e);
            }
        }
    }, "Move Sequences To Bin");
});

We are aware this is less convenient that being able to have asynchronous callbacks. We have received that feature request and are tracking it.

1 Like