{"record":{"id":"3c2d034a576181df","repo":"paperclipai/paperclip","slug":"uploaderror","errorCode":null,"errorMessage":"${uploadError}","messagePattern":"\\$\\{uploadError\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/plugin-llm-wiki/src/ui/issue-attachments.ts","lineNumber":46,"sourceCode":"export async function uploadIssueAttachmentFile(input: {\n  companyId: string;\n  issueId: string;\n  file: File;\n  fetchImpl?: FetchLike;\n}): Promise<unknown> {\n  const fetchImpl = input.fetchImpl ?? fetch;\n  const form = new FormData();\n  form.append(\"file\", input.file);\n  const response = await fetchImpl(\n    `/api/companies/${encodeURIComponent(input.companyId)}/issues/${encodeURIComponent(input.issueId)}/attachments`,\n    {\n      method: \"POST\",\n      credentials: \"include\",\n      body: form,\n    },\n  );\n  if (!response.ok) {\n    throw new Error(await readUploadError(response));\n  }\n  return response.json();\n}\n","sourceCodeStart":28,"sourceCodeEnd":50,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/plugin-llm-wiki/src/ui/issue-attachments.ts#L28-L50","documentation":"Thrown by uploadIssueAttachmentFile() when the POST to /api/companies/:companyId/issues/:issueId/attachments returns a non-OK HTTP status. The message is produced by readUploadError(), which parses the JSON body and prefers body.error, then body.message, falling back to 'Attachment upload failed with HTTP <status>.' This is a pass-through of the server's own error.","triggerScenarios":"Uploading to an issue that does not exist (404). Wrong company scope or missing credentials (401/403). File too large or wrong content-type (413/415). Server error (500). Network blip returning a 5xx.","commonSituations":"Cookie/session expired so credentials: \"include\" no longer authenticates. issueId from a different company. Reverse proxy rejecting multipart bodies above a limit. Temporary backend outage during upload.","solutions":["Inspect response.status — 401/403 means re-authenticate; 404 means wrong companyId/issueId; 413 means shrink the file or raise the server limit.","Retry on transient 5xx with backoff (the upload is idempotent only if the server dedupes; otherwise confirm before retrying).","Ensure credentials: \"include\" is sent alongside a valid session cookie for the Paperclip API origin."],"exampleFix":"// before\nawait uploadIssueAttachmentFile({ companyId, issueId, file }); // bare throw\n// after\ntry {\n  await uploadIssueAttachmentFile({ companyId, issueId, file });\n} catch (err) {\n  if (err instanceof Error && /HTTP 401|HTTP 403/.test(err.message)) {\n    // re-authenticate and retry once\n  } else if (err instanceof Error && /HTTP 413/.test(err.message)) {\n    // file too large — compress or reject\n  } else {\n    throw err;\n  }\n}","handlingStrategy":"try-catch","validationCode":"// pre-flight: ensure the target issue exists and session is valid\nasync function canUpload(fetchImpl: typeof fetch, companyId: string, issueId: string): Promise<boolean> {\n  const r = await fetchImpl(`/api/companies/${encodeURIComponent(companyId)}/issues/${encodeURIComponent(issueId)}`, { credentials: \"include\" });\n  return r.ok;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await uploadIssueAttachmentFile({ companyId, issueId, file });\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  if (/HTTP 401|HTTP 403/.test(msg)) { /* re-auth */ }\n  else if (/HTTP 404/.test(msg)) { /* wrong ids */ }\n  else if (/HTTP 413/.test(msg)) { /* shrink file */ }\n  else throw err;\n}","preventionTips":["Send credentials: \"include\" with a valid session cookie.","Confirm companyId and issueId belong together before upload.","Handle 5xx with bounded retry; surface the server's body.error/message."],"tags":["llm-wiki","attachments","network","http"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}