PS 23.3 broke all my plugins

I came back from holidays and noticed that all my UXP API 2 plugins are broken. All of them rely on the input event. Working fine until 23.2.2.
I had to refund more than €3000 to customers who bought my plugins in the meantime. I’m in a really bad financial situation now and i have to stop selling licenses until this issue is resolved. I’m not amused.

I find no changelogs for the API. Github is empty, i’m getting 404s, or find changelogs stopping at 22.4.0.
So could someone please tell me what has changed in 23.3.0 that makes the input event not fire as it was in 23.2.2?
It behaves weird. When it fires, it acts more like a change event. But mostly it doesn’t execute functions at all, while console logging values always works as expected in real time.
The mousedown and mouseup event seem to have some problem as well. The change event works fine.
I tested on PC with Win10 and Monterey on M1 with the same result.

1 Like

Where are those events? Is it some sp-element?

1 Like

Hi Jarda, thanks for helping. Correct! I’m using sp-elements all over (thought this would be the future).

I tried with native html elements but i have the same results unfortunately.

I’m using sp-textfield in React plugin - no issues with onInput on v23.3.1 or v23.4.0 Beta (Windows 10)

Please try with sp-slider and firing a function oninput that alters the document.

Maybe I’m missing something here, but I’m pretty sure there should be all kinds of weird behavior expected in such case :thinking:

Sliders onInput trigers a lot of times while you’re dragging the slider. State changing actions must be done in executeAsModal(). I’m not even sure how this should work, when it’s called multiple times relatively at once

This is correct but quite easy to deal with by comparing old/new evt values

So far i could reduce it down to the fact that something changed in executeAsModal.
When i fire a function “wrapped” in two console.logs

document.getElementById("testSlider").addEventListener("input", async (evt) => {

  console.log("me firing now!")
  await setTest(
  console.log("Yeh me fired!")


it will mostly(!) not log that it fired, because it didn’t and is stuck in the executeAsModal function. The weird thing is. That it sometimes sporadically fires without obvious reasons.

When wrapping the executeAsModal function in a try/catch clause i’m getting the error “host is in a modal state”.
So i wonder if the PS team did break sliders with input events on purpose for preventing devs building plugins with real time sliders that could mess up the app’s performance by firing too many input events?!

I can confirm that live updates don’t seem to work anymore, which is quite a bummer :confused:
Seems to me like modal states can’t be triggered until the next pointer up…
Here’s what the console logs:

And the before/after comparison of one of my plugins:

I hope that this limitation is not a final decision by Adobe. The live updates (on drag) were running smoothly before without any performance issues.


Thank you Simon. Exactly the same behaviour here.
You can reduce the scope commands with a comparator function, but it still won’t work. Also tried debouncing etc…
Seems like we somehow have to break out the modal state before the next function call happens. But i don’t know how to do that. API 1 still at least had modalBehaviour: wait but in API 2 it’s no longer supported. At least that’s what the error log says.

Not sure it will help, but the last response in this thread has a way to test to see if Ps is in a modal state.

1 Like

Oof… I was just about to implement live slider adjustments on my next plugin. I guess I will postpone that idea for now and let the dust settle before deciding on a plan for it.

I hope Adobe has plans to fix it.

I wonder if it would work better if running in non-modal operation. The interactive flag that was added for 23.3 will run non-modal for UXP API 2. I am using this for places where the user needs to interact with the dialogs. Just an idea.

await require('photoshop').core.executeAsModal(yourFunction, {"commandName": "Your Command Name", "interactive": true});

1 Like

Hi Anthony, thanks for helping. I tried but i was not able to even log the modal state change. Not sure why. Maybe because of the input event. Im also not sure if this would help as we already know when we are in a modal state. That is obviously when we’re executing as modal.
I think the correct event to listen to should be modalJavaScriptScopeEnter and modalJavaScriptScopeExit BTW.

Hi ddbell, thanks for your proposal. I tried with your snippet in various combinations. But no luck. It doesn’t seem to have an effect. I’m getting the same errors.

@kerrishotts if you have the time, could you please try to find out if this is expected behaviour or a bug that will be adressed (evtly possible workaround)?
I’m stuck ATM with literaly zero sales.

Please share a code snippet showing what you’re using to repro the issue so that we have a starting point to work from (w/o us trying to guess how you’re setting things up).

IIRC the default api version for 23.3 is version 2. Previous versions were api version 1. You could force api version 1 in your manifest to see if you can get back to the old behavior for now (don’t know if that will work, but worth a try — unless you have something that really needs api version 2)

Hi Kerri, here comes the snippets.

const exeModal = require('photoshop').core.executeAsModal;
const batchPlay = require("photoshop").action.batchPlay;

const setTest = async function (value) {
  try {
    await exeModal(async function () {
          _obj: "set",
          _target: [{
            _ref: "adjustmentLayer",
            _enum: "ordinal",
            _value: "targetEnum"
          to: {
            _obj: "channelMixer",
            presetKind: {
              _enum: "presetKindType",
              _value: "presetKindCustom"
            red: {
              _obj: "channelMatrix",
              constant: {
                _unit: "percentUnit",
                _value: value
          _options: {}
        }], {});
  } catch (e) {

document.getElementById("testSlider").addEventListener('input', async (evt) => {
  await setTest(;

and markup

<sp-slider class="rtSlider" id="testSlider" min="-100" max="100" value="0" step="1">
            <sp-label slot="label">Test</sp-label>

This is just the basic code without comparator or something that will be needed for throttling the amount of the slider’s input events. Like this it worked in PS 23.2.2 without throwing the error

"Error: host is in a modal state". 

Even when going back to API v1, manifest v4 and when removing exeModal i will get a

{message: "The command failed because Photoshop is in a modal state"}

Using the eventListener onchange works like a charm tho. But only at the drawback of loosing real time changes. Onmousemove will show the same behaviour as oninput.
As long as you drag the mouse with button down, the host is in a modal state. Sometimes it exits the modal state and changes happen. But it seems as long as you fire commands at the host it will prioritize blocking the commands before it will continue executing the commands. Like it is waiting for releasing the mouse button first.
You would think that throttling down the rate of commands would work, but somehow it doesn’t for some reason.
I tried other things to work around this issue, like bulding my own listener with mutationobserver (not supported by UXP) and things. But no luck so far.

I doubt this will change anything, but could you try this instead of adding listener separately?

<sp-slider onInput={(evt) => await setTest(}></sp-slider>

Edit: Oh, this is not React probably. So scratch that. Sorry

1 Like