{"record":{"id":"99dbd895d4ad00ab","repo":"srbhr/Resume-Matcher","slug":"failed-to-update-outreach-message-status-res-st","errorCode":null,"errorMessage":"Failed to update outreach message (status ${res.status}): ${text}","messagePattern":"Failed to update outreach message \\(status (.+?)\\): (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/frontend/lib/api/resume.ts","lineNumber":301,"sourceCode":"}\n\n/** Updates the cover letter for a resume */\nexport async function updateCoverLetter(resumeId: string, content: string): Promise<void> {\n  const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/cover-letter`, { content });\n  if (!res.ok) {\n    const text = await res.text().catch(() => '');\n    throw new Error(`Failed to update cover letter (status ${res.status}): ${text}`);\n  }\n}\n\n/** Updates the outreach message for a resume */\nexport async function updateOutreachMessage(resumeId: string, content: string): Promise<void> {\n  const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/outreach-message`, {\n    content,\n  });\n  if (!res.ok) {\n    const text = await res.text().catch(() => '');\n    throw new Error(`Failed to update outreach message (status ${res.status}): ${text}`);\n  }\n}\n\n/** Renames a resume by updating its title */\nexport async function renameResume(resumeId: string, title: string): Promise<void> {\n  const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/title`, { title });\n  if (!res.ok) {\n    const text = await res.text().catch(() => '');\n    throw new Error(`Failed to rename resume (status ${res.status}): ${text}`);\n  }\n}\n\n/** Downloads cover letter as PDF */\nexport function getCoverLetterPdfUrl(\n  resumeId: string,\n  pageSize: 'A4' | 'LETTER' = 'A4',\n  locale?: Locale\n): string {","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/frontend/lib/api/resume.ts#L283-L319","documentation":"updateOutreachMessage() PATCHes /resumes/:id/outreach-message via apiPatch. Any non-OK HTTP response (4xx/5xx) causes this throw with the status and response body embedded in the message. It is the outreach-message counterpart of the cover-letter save.","triggerScenarios":"Calling updateOutreachMessage(resumeId, content) when the API returns !res.ok: stale resumeId (404), expired auth (401), content rejected by validation (400/422), or backend persistence failure (500).","commonSituations":"Session token expired mid-editing, so the save gets 401; resume deleted or ID malformed leading to 404; outreach text exceeds backend size limits causing 400; transient 502/503 from an API gateway during deploy.","solutions":["Read the status code and body text from the message to pinpoint the failure.","If 401: re-authenticate (token refresh or re-login), then retry the update.","If 404: confirm the resumeId exists and is correct.","If 400/422: validate content length/format against the backend contract and re-save.","If 5xx: retry with backoff; escalate to backend logs if persistent.","Keep the edited text in component state until the save succeeds."],"exampleFix":"// before\nawait updateOutreachMessage(resumeId, content);\n\n// after\ntry {\n  await updateOutreachMessage(resumeId, content);\n} catch (err) {\n  console.error('Outreach save failed:', err.message);\n  setDraft(content); // preserve user input\n  notifyUser('Save failed — check your session and try again.');\n}","handlingStrategy":"try-catch","validationCode":"if (!resumeId || typeof content !== 'string' || content.length > MAX_OUTREACH_LENGTH) {\n  throw new Error('Cannot save outreach message: invalid resumeId or oversized content');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await updateOutreachMessage(resumeId, content);\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  if (/status 40[13]/.test(msg)) triggerRelogin();\n  else if (/status 5\\d\\d/.test(msg)) scheduleRetry(() => updateOutreachMessage(resumeId, content));\n  else notifyUser(`Outreach save failed: ${msg}`);\n}","preventionTips":["Enforce client-side length/format limits matching the backend contract.","Refresh auth tokens proactively before long editing sessions.","Preserve the draft in state until a 2xx confirms the save.","Distinguish retryable (5xx) from permanent (4xx) failures in the catch block."],"tags":["http","api","frontend","resume"],"backgroundTag":"http-non-ok-response","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}