paperclipai/paperclip · error

Cloud runtime identity stack does not match this instance

Error message

Cloud runtime identity stack does not match this instance

What it means

verifyCloudRuntimeIdentityAssertion checks that the assertion's sub claim names the exact stack this instance belongs to (PAPERCLIP_CLOUD_STACK_ID). It throws when PAPERCLIP_CLOUD_STACK_ID is unset or when the assertion was minted for a different stack id, so a foreign runtime identity cannot claim this instance.

Source

Thrown at server/src/services/cloud-runtime-identity.ts:326

    || payload.exp - payload.iat > MAX_ASSERTION_LIFETIME_SECONDS
  ) {
    throw new Error("Cloud runtime identity assertion is expired or has an invalid lifetime");
  }
  return payload as RuntimeIdentityClaims;
}

/** Verify that an assertion is signed for this exact, still-unclaimed instance. */
export function verifyCloudRuntimeIdentityAssertion(input: {
  compactJws: string;
  env?: NodeJS.ProcessEnv;
  now?: Date;
  expectedPreviousOrigin: string | null;
}): RuntimeIdentityClaims {
  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;
}

View on GitHub (pinned to 01ad858492)

Solutions

  1. Set PAPERCLIP_CLOUD_STACK_ID in the instance environment to the stack id the assertion was minted for
  2. Re-mint the assertion with sub equal to this instance's stack id
  3. Confirm the assertion delivery is targeting the correct instance/stack
  4. Log claims.sub (server-side) and compare against env to diagnose mismatch

Example fix

// before
PAPERCLIP_CLOUD_STACK_ID=   # unset
// after
PAPERCLIP_CLOUD_STACK_ID=stack_01hxyz   # matches assertion sub claim
Defensive patterns

Strategy: validation

Validate before calling

const configured = process.env.PAPERCLIP_CLOUD_STACK_ID;
const sub = decodeJwtPayload(jws).sub;
if (!configured || sub !== configured) throw new Error(`stack mismatch: sub=${sub} configured=${configured}`);

Type guard

function matchesStack(claims: {sub:string}, env: NodeJS.ProcessEnv): boolean {
  return Boolean(env.PAPERCLIP_CLOUD_STACK_ID) && claims.sub === env.PAPERCLIP_CLOUD_STACK_ID;
}

Try / catch

try {
  await applyCloudRuntimeIdentityAssertion({ db, compactJws: jws });
} catch (e) {
  if (e.message.includes('stack does not match')) {
    logger.error({ configured: process.env.PAPERCLIP_CLOUD_STACK_ID }, 'assertion minted for a different stack');
  }
  throw e;
}

Prevention

When it happens

Trigger: applyCloudRuntimeIdentityAssertion or verifyAssertion called where env.PAPERCLIP_CLOUD_STACK_ID is empty/nonEmpty-false, or where claims.sub differs from the configured stack id (e.g. assertion minted for stack A delivered to an instance of stack B).

Common situations: PAPERCLIP_CLOUD_STACK_ID not set in the instance environment; copy-pasting an assertion between dev/staging/prod stacks; re-pointing an instance to a new stack without re-minting the assertion; stale container images with old stack env.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/37c2f554350d9025. Report an issue: GitHub.