Found while implementing #14879, which is the same defect on the sibling key. Not that PR's change and not addressed there.
The shape
metadata.prefix moves the mounted metadata routes and the advertised discovery document together, exactly as crud.dataPrefix does for the data routes:
- REST mounts them as
metaPath = basePath + metadata.prefix (packages/rest/src/rest-server.ts, locate by the metaPath symbol -- line numbers in this file have been moving).
- The discovery handler advertises the same value:
discovery.routes.metadata = realBase + this.config.metadata.prefix.
MetadataEndpointsConfigSchema.prefix in packages/spec declares .default('/meta'), so a deployment may set another.
ScopedEnvironmentClient in packages/client/src/index.ts writes /meta as a literal in 5 call sites (this.url('/meta...'), locate by symbol). On a deployment that moves metadata.prefix, that surface calls paths the server does not mount.
Why this is not just #14879 restated
It is the same class on a different key, and the asymmetry #14879's triage identified holds here too: the UNSCOPED metadata methods on the same client already read the advertised value through getRoute('metadata'), so one SDK disagrees with itself about where the metadata routes are -- the unscoped half reads, the scoped half guesses.
Status of the evidence
Stated from reading the three sources above, NOT from a failing probe: unlike the data half, no fixture here was driven against a non-default metadata.prefix. The reproduction would be the one #14879's PR builds for the data key, with metadata: { prefix: ... } in place of crud: { dataPrefix: ... }. Worth confirming with that probe before the fix is graded.
Why it was not fixed in the #14879 PR
The fence on #14879 scopes that card to crud.dataPrefix. The fix model now exists in the file -- #14879 adds _dataPrefix(), which recovers the prefix from the advertised routes and declines to the convention when the document does not determine it -- but a second key needs its own derivation and its own fixture, which is verification surface that card does not own. Applying the same model here should be mechanical once someone claims it.
Dedupe
Targeted search over open and closed: nothing names the scoped SDK's /meta literal against metadata.prefix. #12106 (closed) is the nearest neighbour -- SDK metadata methods building URLs against mounts of the wrong arity -- a different failure on the same methods.
Generated by Claude Code
Found while implementing #14879, which is the same defect on the sibling key. Not that PR's change and not addressed there.
The shape
metadata.prefixmoves the mounted metadata routes and the advertised discovery document together, exactly ascrud.dataPrefixdoes for the data routes:metaPath = basePath + metadata.prefix(packages/rest/src/rest-server.ts, locate by themetaPathsymbol -- line numbers in this file have been moving).discovery.routes.metadata = realBase + this.config.metadata.prefix.MetadataEndpointsConfigSchema.prefixinpackages/specdeclares.default('/meta'), so a deployment may set another.ScopedEnvironmentClientinpackages/client/src/index.tswrites/metaas a literal in 5 call sites (this.url('/meta...'), locate by symbol). On a deployment that movesmetadata.prefix, that surface calls paths the server does not mount.Why this is not just #14879 restated
It is the same class on a different key, and the asymmetry #14879's triage identified holds here too: the UNSCOPED metadata methods on the same client already read the advertised value through
getRoute('metadata'), so one SDK disagrees with itself about where the metadata routes are -- the unscoped half reads, the scoped half guesses.Status of the evidence
Stated from reading the three sources above, NOT from a failing probe: unlike the data half, no fixture here was driven against a non-default
metadata.prefix. The reproduction would be the one #14879's PR builds for the data key, withmetadata: { prefix: ... }in place ofcrud: { dataPrefix: ... }. Worth confirming with that probe before the fix is graded.Why it was not fixed in the #14879 PR
The fence on #14879 scopes that card to
crud.dataPrefix. The fix model now exists in the file -- #14879 adds_dataPrefix(), which recovers the prefix from the advertised routes and declines to the convention when the document does not determine it -- but a second key needs its own derivation and its own fixture, which is verification surface that card does not own. Applying the same model here should be mechanical once someone claims it.Dedupe
Targeted search over open and closed: nothing names the scoped SDK's
/metaliteral againstmetadata.prefix. #12106 (closed) is the nearest neighbour -- SDK metadata methods building URLs against mounts of the wrong arity -- a different failure on the same methods.Generated by Claude Code