srbhr/Resume-Matcher · error · Error

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

Error message

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

What it means

deleteResume removes a resume by ID via apiDelete to /resumes/{id} and throws this Error (with status and response body text) when the response is not OK. It means the server refused or failed to delete the resume record. Raised in confirmDeleteAndReupload and handleDeleteResume flows.

Source

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

  resumeId: string,
  settings?: TemplateSettings,
  locale?: Locale
): Promise<Blob> {
  const url = getResumePdfUrl(resumeId, settings, locale);
  const res = await apiFetch(url);
  if (!res.ok) {
    const text = await res.text().catch(() => '');
    throw new Error(`Failed to download resume (status ${res.status}): ${text}`);
  }
  return await res.blob();
}

/** Deletes a resume by ID */
export async function deleteResume(resumeId: string): Promise<void> {
  const res = await apiDelete(`/resumes/${encodeURIComponent(resumeId)}`);
  if (!res.ok) {
    const text = await res.text().catch(() => '');
    throw new Error(`Failed to delete resume (status ${res.status}): ${text}`);
  }
}

/** 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) {

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check status in the message: 404 -> refresh the resume list (item already gone, treat as success); 401/403 -> re-authenticate.
  2. Inspect the body text for backend-specific refusals (e.g. cannot delete master resume) and adjust the UI to prevent such deletes.
  3. After a failed delete, re-fetch fetchResumeList to re-sync UI state with the server.
  4. Catch the error in handleDeleteResume/confirmDeleteAndReupload and show the server's reason to the user instead of an unhandled rejection.

Example fix

// before
await deleteResume(resumeId);
setResumes(resumes.filter((r) => r.id !== resumeId));

// after
try {
  await deleteResume(resumeId);
} catch (e) {
  console.error('Delete failed:', (e as Error).message);
  notifyUser(`Delete failed: ${(e as Error).message}`);
  return;
}
setResumes(resumes.filter((r) => r.id !== resumeId));
Defensive patterns

Strategy: try-catch

Validate before calling

const list = await fetchResumeList(false);
if (!list.some((r) => r.id === resumeId)) {
  console.warn('Resume already gone; skipping delete');
  return;
}

Type guard

function isDeletableResume(r: ResumeListItem): boolean {
  return typeof r?.id === 'string' && r.id.length > 0;
}

Try / catch

try {
  await deleteResume(resumeId);
} catch (e) {
  if ((e as Error).message.includes('status 404')) {
    setResumes((rs) => rs.filter((r) => r.id !== resumeId)); // already deleted
    return;
  }
  notifyUser(`Delete failed: ${(e as Error).message}`);
}

Prevention

When it happens

Trigger: apiDelete(`/resumes/${encodeURIComponent(resumeId)}`) returns non-2xx: unknown/expired resumeId (404), auth failure (401/403), backend refusing deletion of a master/in-use resume (409/400), or persistence error (500).

Common situations: Deleting a resume that another tab already removed (404); attempting to delete a master resume the backend protects; dev database reset leaving stale UI entries; session expiry after idling on the resume management page.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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