How to know which batchPlay actions require executeAsModal? Is there any downside to executing ALL as modal?

The Adobe documentation is pretty vague on this. It doesn’t seem to provide any kind of list of operations that do or don’t require being executed as modal.

With that in mind, just for the sake of simplifying the process of testing something, having it fail, and only then realizing maybe I need to try to executeAsModal, what if for any batchPlay action, I just by default executed as modal? Would that work? Or would certain operations fail if I tried to execute it that way if they’re not set up to work that way?


Anything that changes the state of Ps, requires modal execution. So basically only getting values doesn’t

…That’s what I mean when I say it’s unclear when this applies. Not to get too philosophical, but it seems like you could argue practically ANYTHING could “change the state of Photoshop.”

“So basically only getting values doesn’t”

So maybe we could think of it like: Non-modal-execution = “read-only” operations; modal execution = “write” operations? I’m not even sure what you’ve said is correct, by the way. I have a command that modifies a Smart Object’s contents that does not use modal execution:

    const descriptor = {
        _obj: "placedLayerReplaceContents",
        null: {
            _path: fileToken,
            _kind: "local"

    try {
        await app.batchPlay([descriptor], { synchronousExecution: true });

Does the fact that I explicitly specified synchronousExecution provide a workaround for this rule? Or are there just some commands that do or don’t require it? Some kind of list from Adobe would be helpful on this.


For the rest of your comment, I agree it’s confusing, but I still use modal if operation modifies anything. Just to be sure

So Adobe will ALLOW me to use executeAsModal for basically any operation I want? If I wanted to be extra safe, I could just be very liberal with my use of that and it won’t throw any kind of “executeAsModal technically not required for this” type of error?

I don’t think it will hurt anything to use it. I have some very long sequences that will run under one history state with one executeAsModal wrapper. Some of the steps need it and some don’t but everything is under the same executeAsModal so that the entire operation can be consolidated into a single history state. It has never caused any issues.

1 Like

executeAsModal doesn’t seem to be REQUIRED for a lot of operations, though. For example, in my plugin, I resize images, I open/close documents, I save JPEGs using various quality settings – and nowhere do I use executeAsModal, yet it lets me perform all of these operations just fine in the plugin.

If an operation flat-out required executeAsModal, I assume Photoshop would throw an error of some kind that would say: “Needs to be run via executeAsModal”? Is that correct?

Or does it allow you to run anything and everything without executeAsModal, making it more of just an additional option but not a requirement for anything?

If an operation flat-out required executeAsModal, I assume Photoshop would throw an error of some kind that would say: “Needs to be run via executeAsModal”? Is that correct?

Yes, for situations where executeIsModal is required the code will not work and you will get a warning in the console.

I would like to mention that it is useful to wrap code with executeAsModal if it is work intensive. This can ensure that the steps are executed faster and no other plugin or Photoshop can “interfere”. Here an example where executeAsModal helped me to run the operation faster even if it wasn’t required.

As a general rule, I don’t enclose “getters” in executeAsModal, especially if they are being called using addNotificationListener, where I might not know when they are triggered, or a setTimeout()function, where a function continuously calls a getter. Getters don’t change the Photoshop UI, and so they don’t need to be in executeAsModal, and slavishly putting them there could cause problems with your plugin or others when you call external functions from within an executeAsModal function. Most getters execute so quickly that the time difference would not be noticeable, the example @tomzag links being an exception, but that exception only occurred when the user had hundreds or thousands of actions on the Ps Actions panel, i.e. work-intensive.

Forgot to mention that executeAsModal is only needed with API version 2.

1 Like

btw: If you do not state this property and value explicitly in the manifest then it will be calculated automatically based on the minimal required PS version.