batchPlay "open image" operation is failing on Mac computer. Works on Windows. Any reason why?

I have this section of code at one point in my plugin, which uses batchPlay to open a given image file in Photoshop:

    const openDocumentToken = await fs.createSessionToken(current_image);
    const open_specified_image_file = {
        _obj: "open",
        null: {
            _path: openDocumentToken,
            _kind: "local"
        }
    };

    await app.batchPlay([open_specified_image_file]);

and the variable current_image comes from a section earlier that basically says “for (const current_image of all_images_to_use)”. And all_images_to_use is defined as such:

// this is specified earlier, I just put them both here to simplify
input_folder_to_use = await fs.getFolder(); 
 // this technically runs later in the code, but this is the sequence
all_images_to_use = await input_folder_to_use.getEntries(input_folder_to_use);

For whatever reason, this open image file operation fails (which causes the next operations to fail in turn.) It’s a computer someone else is using, and I can’t personally debug the code on their same Mac. Any idea why this would only happen on a Mac computer?

I’m gonna guess what you are looking for is the path module:

In a nutshell, paths are written differently depending on OS and the path module will make them cross-platform.

I’m a bit confused though. Is the batchPlay operation Windows specific? Does creating the token like I do in the above code sections not work properly for Mac filepaths?

Apologies, I skim read and thought you were using the whole getEntryFromUrl approach.
AFAIK you’re correct, the API should handle that for you.

Hmm, any ideas what might cause that open operation to fail then? It’s a pretty simple chunk of code and I’m scratching my head trying to figure it out.

Note that I use the same syntax at an earlier step (to open a Photoshop document), and it appears to work just fine. But for some reason at this step, to open the image files, it doesn’t want to work.

    const openDocumentToken = await fs.createSessionToken(photoshop_document_to_use);
    const open_specified_photoshop_document = {
        _obj: "open",
        null: {
            _path: openDocumentToken,
            _kind: "local"
        }
    };

    let open_document_status = "to be determined";
    let openDoc = await app.batchPlay([open_specified_photoshop_document]);

So here’s the concise version of all the pertinent code sections:

const fs = require("uxp").storage.localFileSystem;
input_folder_to_use = await fs.getFolder(); // prompts the user to select a directory
all_images_to_use = await input_folder_to_use.getEntries(input_folder_to_use);

for (const current_image of all_images_to_use) {

    const openDocumentToken = await fs.createSessionToken(current_image);
    const open_specified_image_file = {
        _obj: "open",
        null: {
            _path: openDocumentToken,
            _kind: "local"
        }
    };

    await app.batchPlay([open_specified_image_file]);
    
}

The code is not actually written like that – that’s just like, the super compact version of the sequence of events, for the sake of seeing what happens in what order, where the variables come from, etc.

The current_image or all_images_to_use variables are unlikely to be the problem. It uses those earlier with no error. The batchPlay syntax itself isn’t the issue as this same Mac user opens other documents elsewhere in the code using that identical syntax.

My guess is that it fails because of something related to this line:

const openDocumentToken = await fs.createSessionToken(current_image);

The manifest permissions are set like so:

    "requiredPermissions": {
        "localFileSystem": "fullAccess"
    }   

Even weirder, the operation in question worked exactly ONE time for the user. It failed every other time. The one thing they did differently when it worked, was create a new folder in the original image folder, and added one single image into it. They then re-specified the input folder at the section where they input that, and it worked that one single time. Every other time, the operation just failed to open any images.

I wish I had a Mac computer to test it on!

@Jarda - Any ideas?

hi
does the console show anything at all?
try wrapping relevant code in a try/catch so we may get an error message
also try logging relevant variables so we may know what’s missing
console.log an entry should spit a valid object in the console/inspector

I wish I could. My computers are both Windows, this user is on Mac. Which currently relegates me to, watching session recordings, examining where in the sequence of events it failed, scrutinizing the code and wracking my brain to desperately try to figure out what could’ve possibly went wrong. Debugging/developing Photoshop plugins is hard enough as is. Doing it WITHOUT the ability to console log is just borderline downright moronic.

I honestly see if I might be able to like, use some “remote into a mac” online service to test it on there or something. Or just find some kind of internet cafe or library nearby that has mac computers or something so i can test it.

ok I understand.
for the future, one option is to log to a .log/.txt file.
for now I’m wondering… is there any reason why you’re using batchPlay instead of app.open(entry)?

if your client is willing to help, you can make sure you have a valid token/entry by showing it to him using alert() in a special debug build

this should narrow down the issue

No reason other than the fact that this was the first working method I found to successfully open an image file or PSD document. Could I literally just write app.open(current_image) as a oneliner, and have it work?

Yes, I’m considering working more with the client on this to partner with them on debugging it. I’d give them a version of the plugin complete with a bunch of debug statements at the pertinent section, they’d show me the console log and/or send me the .txt file that it’s all logged to so I can figure it out.

Update: Replaced that whole codeblock with this, and it literally works as a one-liner:

await app.open(current_image);

Given that the problem was PROBABLY related to the batchPlay operation / the createSessionToken part of it? That MAY have just solved the problem. If it does, I’ll report back + let you guys know. Thanks!!!

I have another function that uses batchPlay to open the relevant Photoshop document(s). Is this just totally unnecessary, and I could’ve written this also as a more compact one-liner that says app.open(photoshop_document_to_use)? Are there any circumstances where you DO need to use batchPlay to open a document/file in Photoshop, where this app.open() method will not work?

async function open_photoshop_document() {

    const openDocumentToken = await fs.createSessionToken(photoshop_document_to_use);
    const open_specified_photoshop_document = {
        _obj: "open",
        null: {
            _path: openDocumentToken,
            _kind: "local"
        }
    };

    let open_document_status = "to be determined";
    let openDoc = await app.batchPlay([open_specified_photoshop_document]);

    if (openDoc[0].message === "The parameters for command “Open” are not currently valid.") {open_document_status = "failed"};
    if (openDoc[0]._obj !== "open") {open_document_status = "failed"}; // this is a double-check safeguard (in case, for example, the openDoc[0].message on failure changes in the future.)
    if (open_document_status === "failed") {await app.showAlert(`This Photoshop document can't be found!: ${photoshop_document_to_use.name}. (It may have been moved or deleted.)`)};

    return open_document_status;
}

app.open uses batchplay under the hood.

it accept an entry instead of a token so less code and it’s written by the uxp team so it should handle most cases that we might not think about

I see no need for bp for your use case

For reference, - in the past when I had a client with plugin issues that I was unable to reproduce locally I added a console panel to the plugin. Pretty easy to implement.

I think Sentry would work too. It did in CEP. You could fix errors before are reported by customer :smiley: Application Performance Monitoring & Error Tracking Software

FYI to all: The root cause of the problem was “Apple doubles” – pesky duplicate image files that Mac operating systems often create, which contain metadata/info associated with each image. These are often hidden from Mac users, which made this way harder to debug. The fix was to basically screen out these Apple doubles so that the operations didn’t try to act on them.

2 Likes