{"record":{"id":"6896c0bd4af0ef27","repo":"paperclipai/paperclip","slug":"persisted-cloud-runtime-identity-does-not-match-pa","errorCode":null,"errorMessage":"Persisted Cloud runtime identity does not match PAPERCLIP_CLOUD_STACK_ID","messagePattern":"Persisted Cloud runtime identity does not match PAPERCLIP_CLOUD_STACK_ID","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"server/src/services/cloud-runtime-identity.ts","lineNumber":160,"sourceCode":"\n  const existingCandidates = (() => {\n    try {\n      const parsed = JSON.parse(env.PAPERCLIP_RUNTIME_API_CANDIDATES_JSON ?? \"[]\");\n      return Array.isArray(parsed) ? parsed.filter((value): value is string => typeof value === \"string\") : [];\n    } catch {\n      return [];\n    }\n  })();\n  env.PAPERCLIP_RUNTIME_API_CANDIDATES_JSON = JSON.stringify([\n    identity.canonicalOrigin,\n    ...existingCandidates.filter((candidate) => candidate !== identity.canonicalOrigin),\n  ]);\n}\n\nfunction assertPersistedIdentityMatchesStack(row: PersistedRuntimeIdentity, env: NodeJS.ProcessEnv) {\n  const configuredStackId = nonEmpty(env.PAPERCLIP_CLOUD_STACK_ID);\n  if (!configuredStackId || configuredStackId !== row.stackId) {\n    throw new Error(\"Persisted Cloud runtime identity does not match PAPERCLIP_CLOUD_STACK_ID\");\n  }\n  if (!exactHttpsOrigin(row.previousOrigin) || !exactHttpsOrigin(row.canonicalOrigin)) {\n    throw new Error(\"Persisted Cloud runtime identity contains an invalid origin\");\n  }\n  if (!STACK_SLUG_PATTERN.test(row.stackSlug) || new URL(row.canonicalOrigin).hostname.split(\".\")[0] !== row.stackSlug) {\n    throw new Error(\"Persisted Cloud runtime identity contains an invalid stack slug\");\n  }\n}\n\n/** Load the durable claim before auth, routes, and child-runtime configuration. */\nexport async function initializeCloudRuntimeIdentity(\n  db: Db,\n  env: NodeJS.ProcessEnv = process.env,\n): Promise<CloudRuntimeIdentitySnapshot | null> {\n  startupOrigin = configuredStartupOrigin(env);\n  // Self-hosted servers have no Cloud stack identity to restore. Avoid touching\n  // the singleton table on that path; besides keeping the feature inert, this\n  // preserves lightweight startup/test database seams that intentionally do","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/cloud-runtime-identity.ts#L142-L178","documentation":"Paperclip's Cloud runtime identity is durably persisted in the instance_settings table on first claim. On every startup, initializeCloudRuntimeIdentity reads that persisted row and calls assertPersistedIdentityMatchesStack, which requires PAPERCLIP_CLOUD_STACK_ID in the environment to be present and exactly equal to the stackId stored in the durable claim. This error means the process is running with a stack id that does not match the one this database instance was claimed by, so the runtime refuses to start with a mismatched Cloud identity. It is a fail-fast guard against pointing a claimed instance at the wrong Cloud stack.","triggerScenarios":"initializeCloudRuntimeIdentity is called at startup with PAPERCLIP_CLOUD_STACK_ID set (Cloud mode), a persisted identity row exists, and either (a) PAPERCLIP_CLOUD_STACK_ID is unset/empty/whitespace at this startup even though a claim exists, or (b) its trimmed value differs from row.stackId stored in the durable claim.","commonSituations":"Operators redeploy the instance pointing at the same database but with a wrong or missing PAPERCLIP_CLOUD_STACK_ID env var; an environment/config change (e.g. a stack was recreated with a new id) reuses the old database; a copy of a production database is restored into a different Cloud stack; the env var is injected with different casing or a stale value by the deployment tooling.","solutions":["Set PAPERCLIP_CLOUD_STACK_ID to the exact stackId recorded in the persisted claim (inspect the instanceSettings row with singletonKey 'cloud-runtime-identity/v1' and compare its general.stackId).","If the instance genuinely belongs to a new stack, provision a fresh database for it rather than reusing the claimed database, because the durable claim is single-assignment.","If the env var is simply missing at this startup, restore it from the deployment secret/config that originally supplied it.","If the database row is stale (e.g. an abandoned stack's claim), delete the 'cloud-runtime-identity/v1' instance_settings row only if you are certain the instance was never claimed by an active stack, then restart."],"exampleFix":"// before (deployment env)\nPAPERCLIP_CLOUD_STACK_ID=stack-old-id\n// after (matches the persisted claim's stackId)\nPAPERCLIP_CLOUD_STACK_ID=stack-current-id","handlingStrategy":"validation","validationCode":"// before startup / deploy\nconst configured = process.env.PAPERCLIP_CLOUD_STACK_ID?.trim();\nif (!configured) throw new Error(\"PAPERCLIP_CLOUD_STACK_ID must be set in Cloud mode\");\n// compare against the durable claim\nconst row = await db.select().from(instanceSettings)\n  .where(eq(instanceSettings.singletonKey, \"cloud-runtime-identity/v1\")).limit(1);\nif (row[0] && row[0].general.stackId !== configured) {\n  throw new Error(`Stack id mismatch: env=${configured} persisted=${row[0].general.stackId}`);\n}","typeGuard":"function hasMatchingStackId(env: NodeJS.ProcessEnv, row: { stackId: string } | null): boolean {\n  const configured = env.PAPERCLIP_CLOUD_STACK_ID?.trim();\n  return typeof configured === \"string\" && configured.length > 0 && row !== null && configured === row.stackId;\n}","tryCatchPattern":null,"preventionTips":["Keep PAPERCLIP_CLOUD_STACK_ID in the same deployment secret/config set as the database so they move together","Never restore a claimed database into a different Cloud stack without re-provisioning","Add a deploy-time check comparing the env var with the persisted claim before restarting the server","Pin the stack id in infrastructure-as-code so it cannot drift between environments"],"tags":["cloud","identity","config-mismatch","startup"],"backgroundTag":"invalid-config-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}