srbhr/Resume-Matcher · error · Error

Failed to update resume (status ${res.status}): ${text}

Error message

Failed to update resume (status ${res.status}): ${text}

What it means

updateResume saves edited resume data (ProcessedResume) via apiPatch to /resumes/{id}. On a non-OK response it reads the response body as text and throws this Error including both the status and the server's error message, making it the most diagnostic of the resume read/write errors. It means the backend rejected the resume update.

Source

Thrown at apps/frontend/lib/api/resume.ts:220

}

export async function fetchResumeList(includeMaster = false): Promise<ResumeListItem[]> {
  const res = await apiFetch(`/resumes/list?include_master=${includeMaster ? 'true' : 'false'}`);
  if (!res.ok) {
    throw new Error(`Failed to load resumes list (status ${res.status}).`);
  }
  const payload = (await res.json()) as { data: ResumeListItem[] };
  return payload.data;
}

export async function updateResume(
  resumeId: string,
  resumeData: ProcessedResume
): Promise<ResumeResponse['data']> {
  const res = await apiPatch(`/resumes/${encodeURIComponent(resumeId)}`, resumeData);
  if (!res.ok) {
    const text = await res.text().catch(() => '');
    throw new Error(`Failed to update resume (status ${res.status}): ${text}`);
  }
  const payload = (await res.json()) as ResumeResponse;
  return payload.data;
}

export function getResumePdfUrl(
  resumeId: string,
  settings?: TemplateSettings,
  locale?: Locale
): string {
  const normalizedId = normalizeResumeId(resumeId);
  const params = new URLSearchParams();

  if (settings) {
    params.set('template', settings.template);
    params.set('pageSize', settings.pageSize);
    params.set('marginTop', String(settings.margins.top));
    params.set('marginBottom', String(settings.margins.bottom));

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Read the ${text} portion of the message — it contains the backend's validation/error detail; fix the offending fields in resumeData.
  2. Verify the resumeId still exists (fetchResumeList) before saving; re-sync UI state if it was deleted elsewhere.
  3. Confirm the ProcessedResume shape matches the current backend contract after any API version change.
  4. In runSave, catch the error, surface the server message to the user, and preserve local edits so they are not lost.

Example fix

// before
await updateResume(resumeId, resumeData);

// after
try {
  await updateResume(resumeId, resumeData);
} catch (e) {
  const msg = (e as Error).message;
  console.error('Resume update rejected:', msg); // includes server body
  notifyUser(`Save failed: ${msg}`);
}
Defensive patterns

Strategy: validation

Validate before calling

function isValidProcessedResume(r: ProcessedResume): boolean {
  return typeof r === 'object' && r !== null && 'id' in r;
}
if (!isValidProcessedResume(resumeData)) throw new Error('Invalid resume payload before PATCH');

Type guard

function isProcessedResume(x: unknown): x is ProcessedResume {
  return typeof x === 'object' && x !== null && 'id' in x;
}

Try / catch

try {
  await updateResume(resumeId, resumeData);
} catch (e) {
  const detail = (e as Error).message.split(':').slice(1).join(':').trim();
  notifyUser(`Save failed: ${detail || 'unknown server error'}`);
}

Prevention

When it happens

Trigger: apiPatch(`/resumes/${encodeURIComponent(resumeId)}`, resumeData) returns non-2xx: 422/400 from a ProcessedResume payload failing backend schema validation, 404 for an unknown resumeId, 401/403 for auth issues, or 409/500 from concurrent-edit or persistence failures.

Common situations: Builder 'save' (runSave) submitting resume JSON whose structure no longer matches what the backend expects after an API schema change; saving a resume deleted in another tab; oversized payload or invalid field types (e.g. null where array expected) rejected with 422.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of srbhr/Resume-Matcher@116f9cc3b0 (2026-08-28). Data as JSON: /api/errors/8d1674d87115cc3d. Report an issue: GitHub.