XMP Metadata Access Completely Broken in Photoshop 27 - Critical Regression for UXP Plugin Developers

Summary

After upgrading from Photoshop 26 to 27, all XMP metadata read/write
operations in UXP plugins have stopped working. This appears to be an
undocumented breaking change that affects any plugin using XMP metadata
functionality.

Background

I maintain several UXP plugins that rely heavily on XMP metadata for
storing application data within Photoshop documents. These plugins worked
flawlessly in PS 26 and earlier versions. I also recently published “The
Definitive Guide to UXP XMP Integration” documenting best practices for
XMP operations in UXP.

What Worked in PS 26

The following standard XMP operations worked reliably:

// Direct XMP access (PS 26)
const doc = app.activeDocument;
const rawXMP = doc.xmpMetadata.rawData;
const xmp = new XMPMeta(rawXMP);
const value = xmp.getProperty(XMPConst.NS_DC, “description”);

// XMP writing (PS 26)
xmp.setProperty(XMPConst.NS_DC, “description”, “test data”);
doc.xmpMetadata.rawData = xmp.serialize();

// BatchPlay XMP access (PS 26)
const result = await action.batchPlay([{
“_obj”: “get”,
“_target”: [{ “_ref”: “property”, “_property”: “xmpMetadata” }]
}], {});

What’s Broken in PS 27

Complete XMP metadata access failure:

  1. Direct API Access:
    console.log(app.activeDocument.xmpMetadata); // → undefined/false
  2. ExecuteAsModal Context:
    await core.executeAsModal(async () => {
    const doc = app.activeDocument;
    console.log(!!doc.xmpMetadata); // → false
    console.log(!!doc.xmpMetadata?.rawData); // → false
    });
  3. BatchPlay Commands:
    // Returns error -25920: “The command ‘Get’ is not currently available”
    const result = await action.batchPlay([{
    “_obj”: “get”,
    “_target”: [{ “_ref”: “property”, “_property”: “xmpMetadata” }]
    }], {});

Test Case & Reproduction

I created a comprehensive test plugin to isolate this issue. The test
consistently shows:

  • ✓ Document exists: “Untitled-1”
  • ✗ Direct xmpMetadata: false
  • ✗ Modal xmpMetadata: false
  • ✗ BatchPlay fails: error -25920

Console Output:
[XMP-EXISTS] Document exists: “Untitled-1”
[XMP-EXISTS] Direct xmpMetadata: false
[XMP-EXISTS] Modal xmpMetadata: false
[XMP-EXISTS] BatchPlay failed: XMP Write Test: The command “Get” is not
currently available.

Impact on Plugin Ecosystem

This regression affects:

  • Document-specific data storage via XMP
  • Custom metadata workflows
  • Integration with File > File Info dialog
  • Cross-application metadata compatibility
  • Any plugin following Adobe’s documented XMP patterns

My production plugin “Noteli” (a note-taking tool that stores notes in
XMP) completely stopped functioning after users upgraded to PS 27.

Questions for Adobe

  1. Is this an intentional security restriction or an unintended
    regression?
    • No release notes mention removing XMP access
    • This breaks fundamental plugin functionality without warning
  2. What is the official PS 27 method for XMP operations?
    • Current UXP documentation still shows the broken methods
    • Plugin developers need updated guidance
  3. Will XMP access be restored in a future update?
    • Many plugins depend on this core functionality
    • Need clarity for plugin maintenance planning
  4. Was this change made to restrict developer access to XMP metadata?
    • If intentional, what’s the reasoning behind removing this capability?
    • How should plugins handle document-specific metadata storage now?

Workaround Attempts

I’ve tested various approaches based on community suggestions:

  • PS 27 compatible write pattern using executeAsModal() + save()
  • Alternative XMP module imports (require(‘photoshop’).xmp vs
    require(‘uxp’).xmp)
  • Permission escalation to fullAccess
  • Different timing approaches with delays

None restore basic XMP read access.

Technical Environment

  • Platform: macOS (Darwin 24.6.0)
  • Photoshop: Version 27.x
  • UXP Version: 6.2
  • Plugin Type: Panel with fullAccess permissions
  • Manifest Version: 5

Request for Action

This appears to be a critical regression that breaks existing plugin
functionality. Could Adobe engineering please:

  1. Confirm whether this is intentional or a bug
  2. Provide official guidance for PS 27 XMP operations
  3. Update UXP documentation to reflect current capabilities
  4. Restore XMP access if this was unintended

The plugin developer community needs clarity on this fundamental
capability that many plugins depend on.


Has anyone else experienced this XMP access regression in PS 27? Any
insights or workarounds would be greatly appreciated.

1 Like

Did you try this BP descriptor?

Also check the solution post about the library. I wonder if this still works. At least I didn’t get any complaints and I use this approach in one of my plugins :thinking:

1 Like

I will check it out, thanks. Which library post do you refer to?

The one marked as a solution :slightly_smiling_face:

1 Like

Ah, sorry I looked at that. I will consider, but looking at a different option at the moment that won’t get broken in UXP or PS updates.

1 Like

OK, so after a really hard day I managed to use the info from above to write to the dc:description field, but I cannot make it register a namespace, even if using the same method @DavideBarranca used in his example and solution.
Has PS 27 stopped this access?
Key points:

  • dc:description with setLocalizedText/getLocalizedText works perfectly :white_check_mark:

  • dc:custom_property with setProperty/getProperty fails silently :cross_mark:

  • Same namespace, same XMP methods, different results

  • batchPlay claims success but data vanishes

  • All namespaces properly registered at startup

  • Multiple PS versions tested

Just to add an end note. I played more with the solution mentioned above and can confirm I now have custom namespaces with data in XMP in PS 27! :grinning_face:

2 Likes

I was looking into injecting IRB data, but that got blown out for UXP security reasons.

Still interested to know if this breaking change was a bug and if Adobe will still support direct XMP access via the documented methods. We especially rely on XMP for data storage in InDesign documents.

1 Like

Indeed @Adobe Everything was working fine and now your documented method is broke. I was told it has something to do with Content Credential pipeline and security boosts in that area. Especially the matchplay method throws wobblies even in my new method using the above techniques stated by DavideBarranca

@samgannaway Can you take a look at this one?

1 Like

@samgannaway If you come along Jira, please consider a cross-reference to ID-4267520 for related issues with an InDesign POV and general XMP.

2 Likes

I’m a little confused. app.activeDocument.xmpMetadata is ExtendScript.
XMP is provided under the uxp module: require(‘uxp’).xmp

I would link to the documentation here, but it appears to be broken. Sigh…

I’ll take a look at the descriptors when I get a chance. @DavideBarranca, have you used the XMP support under ‘uxp’?

I don’t know if this helps with troubleshooting, but in InDesign 2026, it works in UXP both with document property and via module (const { XMPMeta, XMPConst, XMPFile } = require(“uxp”).xmp;).

https://developer.adobe.com/indesign/uxp/reference/uxp-api/reference-js/Modules/uxp/XMP/getting-started/

That broken link is for a .md – I think those are only present in the github doc sources.

https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Modules/uxp/XMP/getting-started/

Rob’s example may be missing a bunch of require(), or could it be .psjs ?

My mentioned InDesign case is more about documentation problems common to all uxp.xmp hosts, where Rob’s issues are far deeper into the PS DOM. Interesting to learn that PS also has / had separate XMP support. I may need that soon.

@samgannaway is uxp.xmp file access (as in the linked doc, batch example) supposed to work on PS documents while they are open in PS?

The script snippet isn’t complete. It’s the bare elements to show here. I did write a full report of the process taken to get XMP working, but as soon as I wrote and aired it the system broke. This coincided with PS 27 release. I then took 2 days to implement @DavideBarranca method and it works fine now. I believe this method will also survive PS upgrades too.

1 Like