{"record":{"id":"18f25ae38aaa9dc6","repo":"paperclipai/paperclip","slug":"quota","errorCode":"quota","errorMessage":"Photon Cloud request limit reached; retry later","messagePattern":"Photon Cloud request limit reached; retry later","errorType":"error_code","errorClass":"PhotonError","httpStatus":null,"severity":"warning","filePath":"server/src/services/photon/cloud.ts","lineNumber":147,"sourceCode":"          headers: {\n            authorization: `Basic ${Buffer.from(`${projectId}:${projectSecret}`).toString(\"base64\")}`,\n            accept: \"application/json\",\n          },\n        },\n      );\n    } catch {\n      throw new PhotonError(\n        \"network\",\n        \"Photon Cloud could not be reached; retry the connection\",\n      );\n    }\n    if (response.status === 401 || response.status === 403)\n      throw new PhotonError(\n        \"credentials\",\n        \"Photon rejected this project ID or secret\",\n      );\n    if (response.status === 429)\n      throw new PhotonError(\n        \"quota\",\n        \"Photon Cloud request limit reached; retry later\",\n      );\n    if (!response.ok)\n      throw new PhotonError(\n        \"network\",\n        `Photon Cloud returned HTTP ${response.status}`,\n      );\n    const reader = response.body?.getReader();\n    if (!reader)\n      throw new PhotonError(\n        \"invalid_response\",\n        \"Photon returned an empty response\",\n      );\n    const chunks: Uint8Array[] = [];\n    let length = 0;\n    try {\n      for (;;) {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/cloud.ts#L129-L165","documentation":"Thrown by PhotonCloudClient.request when Photon Cloud responds with HTTP 429, meaning the project has exhausted its request quota / rate limit. The code raises PhotonError 'quota' advising the caller to retry later.","triggerScenarios":"Calling allocation(), inspect(), or the token-minting request (imessage/tokens POST) too frequently for the project's plan; token renewal loops with tight retry intervals; many lines/allocation checks fanning out under one project.","commonSituations":"A retry loop hammering Photon Cloud after earlier network errors; scheduled reconnection storms across many instances sharing one project; free-tier limits exceeded during heavy testing.","solutions":["Back off and retry later with exponential backoff and jitter","Cache allocation/token results and only renew near expiry (the runtime renews at expiresIn*0.8) instead of calling allocation repeatedly","Consolidate multiple instances onto fewer allocation calls or a shared token cache","Upgrade the Photon project plan or request a quota increase if 429s are routine"],"exampleFix":"// before: tight retry loop\nwhile (!ok) { ok = await tryAllocate(cloud, id, secret); }\n// after: honor backoff\nconst delay = Math.min(30_000, 1000 * 2 ** attempt) + Math.random() * 1000;\nawait new Promise(r => setTimeout(r, delay));\nok = await tryAllocate(cloud, id, secret);","handlingStrategy":"retry","validationCode":"// client-side token-budget rate limiter\nlet lastCall = 0;\nasync function throttledAllocate(cloud, id, secret, minIntervalMs = 60_000) {\n  const wait = lastCall + minIntervalMs - Date.now();\n  if (wait > 0) await new Promise(r => setTimeout(r, wait));\n  lastCall = Date.now();\n  return cloud.allocation(id, secret);\n}","typeGuard":"null","tryCatchPattern":"try {\n  return await cloud.allocation(projectId, secret);\n} catch (e) {\n  if (e instanceof PhotonError && e.code === \"quota\")\n    return retryWithBackoff(() => cloud.allocation(projectId, secret), { attempts: 5, baseMs: 30_000, maxMs: 600_000 });\n  throw e;\n}","preventionTips":["Cache allocation/token results until near expiry instead of re-fetching","Rate-limit allocation calls per project on the client side","Use a shared token cache when multiple instances use one project","Add long-base exponential backoff specifically for 429/quota codes","Upgrade the Photon plan if quota errors are recurring"],"tags":["rate-limit","http-429","quota","backoff","retryable"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}