{"record":{"id":"0257b14418b59e1b","repo":"paperclipai/paperclip","slug":"github-attachment-canonical-api-request-failed","errorCode":null,"errorMessage":"github_attachment_canonical_api_request_failed","messagePattern":"github_attachment_canonical_api_request_failed","errorType":"exception","errorClass":"GitHubAttachmentUnavailableError","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-sdk-runtime.ts","lineNumber":2863,"sourceCode":"        `GET ${request.url}`,\n        {\n          headers: {\n            accept: request.accept,\n            \"x-github-api-version\": \"2022-11-28\",\n          },\n          request: {\n            signal,\n            redirect: \"manual\",\n            fetch: githubAttachmentCommentFetch(request, signal),\n          },\n        },\n      );\n      signal.throwIfAborted();\n      return result.data;\n    } catch (error) {\n      // Octokit errors can carry request headers or authenticated HTML. Neither\n      // belongs in adapter logs, durable ingress, nor agent-visible results.\n      throw new GitHubAttachmentUnavailableError(\n        githubAttachmentDiagnosticCode(error) ??\n          \"github_attachment_canonical_api_request_failed\",\n      );\n    }\n  }\n\n  /**\n   * Rebuild an adapter-authenticated download closure after process restart.\n   * Invalid, cross-provider, or no-longer-safe descriptors fail closed.\n   */\n  rehydrateAttachment(\n    descriptor: unknown,\n    source?: ChatSdkAttachmentSource,\n  ): Attachment | null {\n    if (\n      this.provider === \"microsoft-teams\" &&\n      isRecord(descriptor) &&\n      isRecord(descriptor.locator) &&","sourceCodeStart":2845,"sourceCodeEnd":2881,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-sdk-runtime.ts#L2845-L2881","documentation":"The canonical GitHub API request inside resolveGitHubAttachmentComment is wrapped in try/catch; any failure from the octokit request (network error, HTTP error, abort) is rethrown as GitHubAttachmentUnavailableError whose code comes from githubAttachmentDiagnosticCode(error) or, if no specific diagnostic maps, the generic 'github_attachment_canonical_api_request_failed'. Octokit error payloads (headers, HTML bodies) are deliberately stripped to keep them out of logs and durable ingress.","triggerScenarios":"The underlying GET request.url via (adapter as GitHubAdapter).octokit throws: rate limit (403), expired/invalid installation token (401), resource gone (404/410), network failure, or signal abort; githubAttachmentDiagnosticCode does not classify it so the generic code is used.","commonSituations":"GitHub API rate limit exceeded for the installation; GitHub App installation token expired or revoked; repository/issue deleted; transient network outage or timeout during attachment resolution.","solutions":["Read the specific diagnostic code if present; only fall back to treating this as a generic GitHub API failure","Check GitHub App installation status and token freshness; reinstall/refresh the installation if 401/403","Check rate-limit headers and back off before retrying","Verify the request.url still points to an existing GitHub resource and retry with a fresh signal"],"exampleFix":"// before\nconst data = await runtime.resolveGitHubAttachmentComment(request, signal);\n// after\ntry {\n  const data = await runtime.resolveGitHubAttachmentComment(request, signal);\n} catch (e) {\n  if ((e as Error).message === 'github_attachment_canonical_api_request_failed') {\n    // inspect GitHub App installation + rate limits, then retry with backoff\n  }\n}","handlingStrategy":"retry","validationCode":"// preflight: ensure installation token is fresh and url is a valid api.github.com path\nif (!request.url.startsWith('https://api.github.com/')) throw new Error('bad github url');","typeGuard":null,"tryCatchPattern":"try { return await runtime.resolveGitHubAttachmentComment(request, signal); } catch (e) { if ((e as Error).message === 'github_attachment_canonical_api_request_failed') { await backoff(); return runtime.resolveGitHubAttachmentComment(request, signal); } throw e; }","preventionTips":["Back off on GitHub rate limits before retrying","Refresh GitHub App installation tokens proactively","Check that the referenced issue/repo still exists before resolution"],"tags":["github","api-error","octokit","attachments"],"backgroundTag":"api-request-failed","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}