paperclipai/paperclip · error
Cloud runtime identity destination is invalid
Error message
Cloud runtime identity destination is invalid
What it means
After origin checks, verifyCloudRuntimeIdentityAssertion validates the destination identity: stackSlug must match STACK_SLUG_PATTERN, the first hostname label of canonicalOrigin must equal stackSlug, and claimId must be non-empty, trimmed, and at most 256 characters. It throws when the assertion's destination routing data is internally inconsistent.
Source
Thrown at server/src/services/cloud-runtime-identity.ts:340
const env = input.env ?? process.env;
const claims = verifyClaims({ compactJws: input.compactJws, env, now: input.now ?? new Date() });
const configuredStackId = nonEmpty(env.PAPERCLIP_CLOUD_STACK_ID);
if (!configuredStackId || claims.sub !== configuredStackId) {
throw new Error("Cloud runtime identity stack does not match this instance");
}
const previousOrigin = exactHttpsOrigin(claims.previousOrigin);
const canonicalOrigin = exactHttpsOrigin(claims.canonicalOrigin);
if (!previousOrigin || !canonicalOrigin || previousOrigin !== input.expectedPreviousOrigin) {
throw new Error("Cloud runtime identity previous or canonical origin is invalid");
}
if (
!STACK_SLUG_PATTERN.test(claims.stackSlug)
|| new URL(canonicalOrigin).hostname.split(".")[0] !== claims.stackSlug
|| claims.claimId.length > 256
|| claims.claimId.trim() !== claims.claimId
|| !claims.claimId
) {
throw new Error("Cloud runtime identity destination is invalid");
}
return claims;
}
function assertionsEqual(row: PersistedRuntimeIdentity, claims: RuntimeIdentityClaims): boolean {
const left = Buffer.from(JSON.stringify([
row.stackId,
row.claimId,
row.previousOrigin,
row.canonicalOrigin,
row.stackSlug,
]));
const right = Buffer.from(JSON.stringify([
claims.sub,
claims.claimId,
claims.previousOrigin,
claims.canonicalOrigin,
claims.stackSlug,View on GitHub (pinned to 01ad858492)
Solutions
- Re-mint the assertion ensuring canonicalOrigin's first DNS label equals stackSlug and stackSlug passes the slug pattern
- Regenerate claimId as a trimmed non-empty string <= 256 chars
- Compare the minted payload fields against this instance's real hostname before sending
- Check the minter's slug/hostname construction code for drift
Example fix
// before stackSlug: "my-stack", canonicalOrigin: "https://other-stack.example.com" // after stackSlug: "my-stack", canonicalOrigin: "https://my-stack.example.com"
Defensive patterns
Strategy: validation
Validate before calling
const slugOk = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(claims.stackSlug);
const hostOk = new URL(claims.canonicalOrigin).hostname.split('.')[0] === claims.stackSlug;
const idOk = claims.claimId && claims.claimId.length <= 256 && claims.claimId.trim() === claims.claimId;
if (!slugOk || !hostOk || !idOk) throw new Error('destination claims invalid before apply'); Type guard
function validDestination(c: {stackSlug:string;canonicalOrigin:string;claimId:string}): boolean {
try {
return c.claimId.length > 0 && c.claimId.length <= 256 && c.claimId.trim() === c.claimId &&
new URL(c.canonicalOrigin).hostname.split('.')[0] === c.stackSlug;
} catch { return false; }
} Try / catch
try {
await applyCloudRuntimeIdentityAssertion({ db, compactJws: jws });
} catch (e) {
if (e.message.includes('destination is invalid')) {
const claims = decodeJwtPayload(jws);
logger.error({ stackSlug: claims.stackSlug, canonicalOrigin: claims.canonicalOrigin, claimIdLen: claims.claimId?.length }, 'destination claims inconsistent');
}
throw e;
} Prevention
- Derive stackSlug from the canonical hostname's first label at mint time so they can never diverge
- Generate claimId with a fixed trimmed format (e.g. uuid) and cap length
- Add a minter-side pre-send validation mirroring the verifier's checks
- Don't hand-edit or truncate assertion JSON in transit
When it happens
Trigger: Assertion where stackSlug fails the slug regex, canonicalOrigin hostname's first label differs from stackSlug (e.g. origin points at a different stack's hostname), or claimId is empty, has whitespace, or exceeds 256 chars.
Common situations: Minting service generated a slug that doesn't match the DNS name of the canonical origin; assertion fields edited/truncated in transit; claimId generator produced an empty or padded string; cross-stack assertion copy where slug and hostname disagree.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Persisted Cloud runtime identity contains an invalid stack s
- Cloud runtime identity stack does not match this instance
- Cloud runtime identity previous or canonical origin is inval
- Invalid status '${String(rawStatus)}'. Must be one of: ${PLU
- "tool" is required and must be a string
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/0c153cdff4e68d6d.
Report an issue: GitHub.