That’s very good explanation, thank you! I’ll have to edit dozens of functions now but at leas there is a light in the end of the tunnel 
My commands are all inside execModal() and all BPs are synchronous - no luck here 
Hmm, the issue seems to be with the filter dialog. It fails when I apply it but not when I cancel. I’ll log a ticket for investigation.
Yes, adding async/await does resolve the issue. I’d like to get a better handle on the situation and a better error for this type of situation.
Hi @simonhenke,
I’m trying to implement your solution for suspendHistory helper function. It works if I’m using only BP.
But… if I’m trying to do:
batchPlay
DOM
batchplay
or
batchPlay
DOM
I’m getting two history states. I have no idea what I’m doing wrong.
Could you please take a look at the code structure:
async function dbgrey() {
    const docexists = () => {
        return Boolean(app.documents?.length)
      }
      const dexists = docexists()
      
if (dexists === true) {
    suspendHistory(async () => {
        await batchPlay([
         // descriptor 1
         // descriptor 2
         // ...
            ], {});
        await app.activeDocument.activeLayers[0].moveAbove(await app.activeDocument.layers[0]);    
        await batchPlay(
            [
         // descriptor 1
         // descriptor 2
         // ...
            ], {});
        }, "Just one step")
}
else {  PhotoshopCore.showAlert({message: 'Open the document first'});}
}
document.getElementById("btndbgrey").addEventListener("click", dbgrey);
This is your helper that I’m using (I’ve removed “export”):
async function suspendHistory(fn, historyName = "(Plugin command)", commandName = "Waiting for plugin command...") {
    async function executeAsModal(executionContext) {
      const hostControl = executionContext.hostControl;
      const suspensionID = await hostControl.suspendHistory({
          "historyStateInfo": {
              "name": historyName,
              "target": { _ref: 'document', _enum: 'ordinal', _value: 'targetEnum' }
          }
      });
      try {
        fn(executionContext);  
      } catch(e) {console.error(e)}
     await hostControl.resumeHistory(suspensionID);
    }
    await require("photoshop").core.executeAsModal(executeAsModal, {commandName});
  }
I would be very grateful if you could tell me what I’m doing wrong.
I’m using PS 23.4.1 on Mac, API 2, Manifest 5
Thank you!
I think you’re missing await in suspendHistory():
await fn(executionContext);
I believe what happens, is right after you call the callback, also resumeHistory() is called before your function finishes
@Karmalakas, You are right, thank you!
You can also do it in React. Here is an example:
import { app, constants, core } from "photoshop";
import React from "react";
const App = () => {
  const handleClick = async () => {
    try {
      await core.executeAsModal(
        async (executionContext) => {
          let hostControl = executionContext.hostControl;
          let suspensionID = await hostControl.suspendHistory({
            documentID: app.activeDocument.id,
            name: "Custom command",
          });
          const activeLayer = app.activeDocument.activeLayers[0];
          activeLayer?.move(
            app.activeDocument.layers[0],
            constants.ElementPlacement.PLACEBEFORE
          );
          hostControl.resumeHistory(suspensionID);
        },
        { commandName: "Moving layer to the front" }
      );
    } catch (error) {
      console.log(error);
    }
  };
  return <sp-button onClick={handleClick}>Move Layer to Front</sp-button>;
};
export default App;
