paperclipai/paperclip · error · PhotonError

line_unavailable

line_unavailable

Error message

Photon did not supply a dedicated line with a stable phone number

What it means

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.

Solutions

  1. Confirm the Photon project has dedicated lines provisioned and active in the Photon dashboard
  2. If the project is now shared-mode, create a shared PhotonLineAuthentication (allocation:'shared') instead of expecting a dedicated line
  3. Retry later if dedicated numbers are temporarily out of stock; free or acquire numbers in the Photon console
  4. Verify expiresIn/auth/numbers are being returned; if the API contract changed, update the client

Example fix

// before
const auth = new PhotonLineAuthentication({ allocation: 'dedicated', projectId, lineId, phoneNumber }, secret);
// after
const inspection = await cloud.inspect(projectId, secret);
const mode = inspection.allocation; // 'shared' | 'dedicated'
const auth = new PhotonLineAuthentication({ allocation: mode, projectId, lineId, phoneNumber }, secret);
Defensive patterns

Strategy: fallback

Validate before calling

const inspection = await cloud.inspect(projectId, secret);
if (inspection.allocation !== 'dedicated') {
  // route to shared flow instead of expecting a dedicated line
}

Try / catch

try {
  const alloc = await cloud.allocation(projectId, secret);
} catch (e) {
  if (e instanceof PhotonError && e.code === 'line_unavailable') {
    // fall back to shared allocation or surface 'provision dedicated lines' to the operator
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/54560a646aebb125. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/photon/cloud.ts:241

      eligible: false,
      lines: [],
    };
    if (data.type === "shared") {
      if (typeof data.token !== "string" || !data.token || data.token.length > 16_384 ||
          typeof data.expiresIn !== "number" || !Number.isFinite(data.expiresIn) || data.expiresIn < 30)
        throw new PhotonError("invalid_response", "Photon returned invalid shared project credentials");
      inspection.eligible = true;
      return { inspection, sharedToken: data.token, tokens: new Map(), expiresIn: Math.min(data.expiresIn, 86_400) };
    }
    if (
      data.type !== "dedicated" ||
      !record(data.auth) ||
      !record(data.numbers) ||
      typeof data.expiresIn !== "number" ||
      !Number.isFinite(data.expiresIn) ||
      data.expiresIn < 30
    ) {
      throw new PhotonError(
        "line_unavailable",
        "Photon did not supply a dedicated line with a stable phone number",
      );
    }
    const tokens = new Map<string, string>();
    for (const [lineId, token] of Object.entries(data.auth)) {
      if (
        !photonLineIdSchema.safeParse(lineId).success ||
        typeof token !== "string" ||
        !token ||
        token.length > 16_384
      )
        continue;
      const phoneNumber = data.numbers[lineId];
      if (
        typeof phoneNumber !== "string" ||
        !/^\+[1-9]\d{6,14}$/.test(phoneNumber)
      )

View on GitHub (pinned to 3f1d897a7c)