{"record":{"id":"54560a646aebb125","repo":"paperclipai/paperclip","slug":"line-unavailable","errorCode":"line_unavailable","errorMessage":"Photon did not supply a dedicated line with a stable phone number","messagePattern":"Photon did not supply a dedicated line with a stable phone number","errorType":"error_code","errorClass":"PhotonError","httpStatus":null,"severity":"error","filePath":"server/src/services/photon/cloud.ts","lineNumber":241,"sourceCode":"      eligible: false,\n      lines: [],\n    };\n    if (data.type === \"shared\") {\n      if (typeof data.token !== \"string\" || !data.token || data.token.length > 16_384 ||\n          typeof data.expiresIn !== \"number\" || !Number.isFinite(data.expiresIn) || data.expiresIn < 30)\n        throw new PhotonError(\"invalid_response\", \"Photon returned invalid shared project credentials\");\n      inspection.eligible = true;\n      return { inspection, sharedToken: data.token, tokens: new Map(), expiresIn: Math.min(data.expiresIn, 86_400) };\n    }\n    if (\n      data.type !== \"dedicated\" ||\n      !record(data.auth) ||\n      !record(data.numbers) ||\n      typeof data.expiresIn !== \"number\" ||\n      !Number.isFinite(data.expiresIn) ||\n      data.expiresIn < 30\n    ) {\n      throw new PhotonError(\n        \"line_unavailable\",\n        \"Photon did not supply a dedicated line with a stable phone number\",\n      );\n    }\n    const tokens = new Map<string, string>();\n    for (const [lineId, token] of Object.entries(data.auth)) {\n      if (\n        !photonLineIdSchema.safeParse(lineId).success ||\n        typeof token !== \"string\" ||\n        !token ||\n        token.length > 16_384\n      )\n        continue;\n      const phoneNumber = data.numbers[lineId];\n      if (\n        typeof phoneNumber !== \"string\" ||\n        !/^\\+[1-9]\\d{6,14}$/.test(phoneNumber)\n      )","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/cloud.ts#L223-L259","documentation":"For a dedicated allocation, allocation() requires data.type === 'dedicated' plus a valid auth record, numbers record, and a finite expiresIn >= 30. If the project is not on a dedicated plan or the dedicated response lacks these fields, a PhotonError with code 'line_unavailable' is thrown because there is no stable dedicated phone line to use.","triggerScenarios":"Calling allocation()/inspect() on a project whose imessage/tokens response has type 'shared' (checked after the shared branch) or a type other than 'dedicated', or a dedicated response missing auth/numbers/expiresIn or with expiresIn < 30.","commonSituations":"Project switched from dedicated to shared lines in the Photon console; dedicated lines not provisioned or all released; Photon account out of dedicated-number quota; API returning an unexpected shape on degraded service.","solutions":["Confirm the Photon project has dedicated lines provisioned and active in the Photon dashboard","If the project is now shared-mode, create a shared PhotonLineAuthentication (allocation:'shared') instead of expecting a dedicated line","Retry later if dedicated numbers are temporarily out of stock; free or acquire numbers in the Photon console","Verify expiresIn/auth/numbers are being returned; if the API contract changed, update the client"],"exampleFix":"// before\nconst auth = new PhotonLineAuthentication({ allocation: 'dedicated', projectId, lineId, phoneNumber }, secret);\n// after\nconst inspection = await cloud.inspect(projectId, secret);\nconst mode = inspection.allocation; // 'shared' | 'dedicated'\nconst auth = new PhotonLineAuthentication({ allocation: mode, projectId, lineId, phoneNumber }, secret);","handlingStrategy":"fallback","validationCode":"const inspection = await cloud.inspect(projectId, secret);\nif (inspection.allocation !== 'dedicated') {\n  // route to shared flow instead of expecting a dedicated line\n}","typeGuard":null,"tryCatchPattern":"try {\n  const alloc = await cloud.allocation(projectId, secret);\n} catch (e) {\n  if (e instanceof PhotonError && e.code === 'line_unavailable') {\n    // fall back to shared allocation or surface 'provision dedicated lines' to the operator\n  } else throw e;\n}","preventionTips":["Inspect the project's allocation mode before constructing a dedicated identity","Provision and verify dedicated numbers in the Photon console before enabling dedicated channels","Alert on dedicated-number quota exhaustion"],"tags":["phone-line","api","provisioning"],"backgroundTag":"resource-not-found","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}