Issue reference
Your shared-catalogue profile is invalid
- UCP_PROFILE_INVALID
- Find products
- —
- High
What it means
tragent reports this at the “Find products” stage. The question there is “Can an agent find your products at all?” An agent has to reach your site and locate products by searching or browsing before anything else can happen.
What it does to an agent
Most agents fail at this point. The few that find a way round it spend more time and model calls doing so, and may give up before checkout.
A profile that exists but cannot be read is worse than none: an agent that finds /.well-known/ucp commits to the protocol, then stops when the document has no version or no capabilities. tragent reads the profile the way the published versions are shaped, including the nested form Shopify serves, and reports what is missing or unreadable.
The usual causes are an app shell answering every path with HTML, a hand-written profile with a trailing comma, or a profile copied from an older version that put members at a different level.
How to fix it
Correct the profile against the UCP schema; an unparseable profile is worse than none, because agents stop negotiating.
{ "capabilities": ["checkout",], }{
"ucp": {
"version": "2026-08-25",
"capabilities": { "dev.ucp.shopping.checkout": [{ "version": "2026-08-25" }] }
}
}On your platform
Shopify
Shopify generates this document, so an invalid profile on Shopify is rare. If the scan reports one, open the address in a browser: a theme app or proxy answering the path with HTML is the usual cause.
Headless or custom
Generate the profile with a JSON serialiser rather than a template string, and serve it with Content-Type application/json. Validate it against the schema for the version you declare.
In practice
Treat the profile as code: generate it from configuration, check it in, and validate it in CI before it ships. A test that fetches /.well-known/ucp from a staging deploy and parses it catches the app-shell problem, where a single-page app answers every unknown path with its HTML, before a single agent sees it.
When the specification moves to a new dated version, publish the new profile alongside the old one rather than replacing it overnight. The profiles Shopify serves list supported versions with a URL for each, which lets an agent on an older client keep working. tragent reads both the flat shape and the nested shape, and treats a version newer than it pins as its own limitation rather than your failure.
If you cannot tell which part is wrong, compare your profile with a working one. The profile every Shopify store serves is public at its /.well-known/ucp address, and shows the nesting, the version strings and how capabilities are keyed by name. Match the structure first, then the values; most invalid profiles are a structural mistake rather than a wrong value.
Check the fix
- curl -s https://your-store/.well-known/ucp | python3 -m json.tool, which fails loudly on invalid JSON.
- Confirm the Content-Type header says application/json.
- Run the scan; the profile check should read a version and capabilities.
Run the check that reported UCP_PROFILE_INVALID again after the change. The scan needs no account; an issue found during an AI shopping test needs that test run again.
npx @tragent/cli scan https://your-store.comCommon mistakes
- Trailing commas and comments, which JSON does not allow.
- Declaring a version without capabilities, or capabilities as an empty list.
- Caching an old profile at the CDN after changing it at the origin.