srbhr/Resume-Matcher · error · Error
Failed to update outreach message (status ${res.status}): ${
Error message
Failed to update outreach message (status ${res.status}): ${text} What it means
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.
Source
Thrown at apps/frontend/lib/api/resume.ts:301
}
/** Updates the cover letter for a resume */
export async function updateCoverLetter(resumeId: string, content: string): Promise<void> {
const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/cover-letter`, { content });
if (!res.ok) {
const text = await res.text().catch(() => '');
throw new Error(`Failed to update cover letter (status ${res.status}): ${text}`);
}
}
/** Updates the outreach message for a resume */
export async function updateOutreachMessage(resumeId: string, content: string): Promise<void> {
const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/outreach-message`, {
content,
});
if (!res.ok) {
const text = await res.text().catch(() => '');
throw new Error(`Failed to update outreach message (status ${res.status}): ${text}`);
}
}
/** Renames a resume by updating its title */
export async function renameResume(resumeId: string, title: string): Promise<void> {
const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}/title`, { title });
if (!res.ok) {
const text = await res.text().catch(() => '');
throw new Error(`Failed to rename resume (status ${res.status}): ${text}`);
}
}
/** Downloads cover letter as PDF */
export function getCoverLetterPdfUrl(
resumeId: string,
pageSize: 'A4' | 'LETTER' = 'A4',
locale?: Locale
): string {View on GitHub (pinned to 116f9cc3b0)
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.
Example fix
// before
await updateOutreachMessage(resumeId, content);
// after
try {
await updateOutreachMessage(resumeId, content);
} catch (err) {
console.error('Outreach save failed:', err.message);
setDraft(content); // preserve user input
notifyUser('Save failed — check your session and try again.');
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!resumeId || typeof content !== 'string' || content.length > MAX_OUTREACH_LENGTH) {
throw new Error('Cannot save outreach message: invalid resumeId or oversized content');
} Try / catch
try {
await updateOutreachMessage(resumeId, content);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
if (/status 40[13]/.test(msg)) triggerRelogin();
else if (/status 5\d\d/.test(msg)) scheduleRetry(() => updateOutreachMessage(resumeId, content));
else notifyUser(`Outreach save failed: ${msg}`);
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Failed to update cover letter (status ${res.status}): ${text
- Failed to rename resume (status ${res.status}): ${text}
- Failed to download cover letter (status ${res.status}): ${te
- Failed to generate cover letter (status ${res.status}): ${te
- Upload failed for ${fileToUpload.file.name}. Status: ${respo
AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28).
Data as JSON: /api/errors/99dbd895d4ad00ab.
Report an issue: GitHub.