{"record":{"id":"1a93a317c862ba0e","repo":"paperclipai/paperclip","slug":"device-login-promotion-the-credential-has-no-subs","errorCode":null,"errorMessage":"device-login promotion: the credential has no subscription identity","messagePattern":"device-login promotion: the credential has no subscription identity","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapters/codex-local/src/server/adapter-auth-promotion.ts","lineNumber":218,"sourceCode":"  const env = input.env ?? process.env;\n  const companyId = requireSafeCompanyId(input.companyId);\n\n  // 1. Independent readiness check on the exact staged credential. A non-ready\n  //    result rejects the promotion before any validation or write.\n  const readiness = await checkReadiness(authBytes);\n  if (!readiness.ready) {\n    throw new DeviceLoginReadinessError(readiness.reason ?? \"not_ready\");\n  }\n\n  // 2. Validate the credential with the export rules. This rejects an empty, an\n  //    oversized, an API-key, a non-subscription, and a malformed payload.\n  assertUsableSubscriptionShape(authBytes);\n  const accountId = readSubscriptionAccountId(authBytes);\n  if (!accountId) {\n    // The shape gate above already guarantees a subscription identity; this guard\n    // keeps the account_id non-null for the handle conversion without a non-null\n    // cast.\n    throw new Error(\"device-login promotion: the credential has no subscription identity\");\n  }\n\n  // 2b. Convert the identity into a safe account handle. The handle names both\n  //     this account's own home directory and its company secret, so a login\n  //     whose identity cannot form one must fail before any write.\n  const accountHandle = toAccountHandle(accountId);\n  if (!accountHandle) {\n    throw new Error(\"device-login promotion: the account identifier cannot form a valid account handle\");\n  }\n\n  // 3. Decision C: only a user-initiated login seeds a home.\n  if (!userInitiated) {\n    await log(\"[paperclip] Codex device-login promotion: skipped (an automatic background login never seeds a home).\");\n    return { outcome: \"background_skipped\", accountId, accountHomeDir: null, accountHomeCreated: false };\n  }\n\n  // 4. Decision H: write only while the session still owns the active slot.\n  const soleOwner = await isSoleActiveOwner();","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/adapters/codex-local/src/server/adapter-auth-promotion.ts#L200-L236","documentation":"Guard in promoteDeviceLoginCredential: the staged device-login credential passed the readiness check but has no subscription identity attached, so it cannot be promoted. The credential payload lacks the subscription binding the promotion path requires (distinct from shape validation failures like empty/oversized/API-key payloads, which fail earlier in assertUsableSubscriptionShape).","triggerScenarios":"Thrown at packages/adapters/codex-local/src/server/adapter-auth-promotion.ts:218 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-run the device login flow with a subscription-backed account so the credential carries a subscription identity","Confirm the account actually holds a subscription before promoting","Retry the login; a partially captured credential may be missing the identity claim"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}