{"record":{"id":"c680860f740b2e74","repo":"paperclipai/paperclip","slug":"external-object-refresh-claim-did-not-return-a-ref","errorCode":null,"errorMessage":"External object refresh claim did not return a refresh token","messagePattern":"External object refresh claim did not return a refresh token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/external-objects.ts","lineNumber":996,"sourceCode":"      return { object: toObjectPayload(object, now), refreshed: false, reason: \"backoff\" as const };\n    }\n\n    const refreshKey = `${object.companyId}:${object.id}`;\n    const existingRefresh = objectRefreshesInFlight.get(refreshKey);\n    if (existingRefresh) return existingRefresh;\n\n    const claimed = await claimObjectRefresh(object, input, now);\n    if (!claimed) {\n      const latest = await db\n        .select()\n        .from(externalObjects)\n        .where(and(eq(externalObjects.id, object.id), eq(externalObjects.companyId, object.companyId)))\n        .then((rows) => rows[0] ?? null);\n      if (!latest) throw notFound(\"External object not found\");\n      return { object: toObjectPayload(latest, now), refreshed: false, reason: \"refresh_in_progress\" as const };\n    }\n    if (!claimed.refreshToken) {\n      throw new Error(\"External object refresh claim did not return a refresh token\");\n    }\n\n    const stopRenewingRefreshLease = startRefreshLeaseRenewal(object, claimed.refreshToken);\n    const refresh = resolveObjectRefresh(object, input, now, claimed.refreshToken).finally(() => {\n      stopRenewingRefreshLease();\n      objectRefreshesInFlight.delete(refreshKey);\n    });\n    objectRefreshesInFlight.set(refreshKey, refresh);\n    return refresh;\n  }\n\n  async function refreshIssueObjects(issueId: string, input: {\n    companyId: string;\n    objectIds?: string[];\n    actor?: Pick<LogActivityInput, \"actorType\" | \"actorId\" | \"agentId\" | \"runId\">;\n  }) {\n    if (!(await isEnabled())) return [];\n    const groups = await listForIssue(issueId);","sourceCodeStart":978,"sourceCodeEnd":1014,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/server/src/services/external-objects.ts#L978-L1014","documentation":"Invariant guard in externalObjectService's refresh path: claimObjectRefresh reported the refresh as claimed but produced no refresh token. Without the token the caller cannot complete/commit the refresh, so the claim is treated as malformed rather than proceeding token-less.","triggerScenarios":"Thrown at server/src/services/external-objects.ts:996 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check the external object provider's claim flow; ensure a refresh token is returned and stored."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}