srbhr/Resume-Matcher · error · Error

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

Error message

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

What it means

downloadResumePdf fetches a generated PDF blob for a resume via GET on the URL built by getResumePdfUrl (resume id, optional render settings and locale). If the response is not OK it captures the body text and throws this Error with the status and server detail; the caller's blob() then never receives data. It indicates PDF generation/download failed server-side.

Source

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

    params.set('pageSize', 'A4');
  }
  if (locale) {
    params.set('lang', locale);
  }

  return `${API_BASE}/resumes/${encodeURIComponent(normalizedId)}/pdf?${params.toString()}`;
}

export async function downloadResumePdf(
  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(() => '');

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Inspect status + body text in the message; a 500 usually requires checking backend PDF-render logs for the failing resume content.
  2. Validate the settings/locale values passed to getResumePdfUrl against what the backend supports (400/422).
  3. Confirm the resume still exists before attempting download (404) and refresh the resume list.
  4. Catch the error in the UI, show a download-failed toast, and offer a retry of the PDF fetch.

Example fix

// before
const blob = await downloadResumePdf(resumeId, settings, locale);

// after
let blob: Blob;
try {
  blob = await downloadResumePdf(resumeId, settings, locale);
} catch (e) {
  console.error('PDF download failed:', (e as Error).message);
  notifyUser('Could not download PDF — please retry.');
  return;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const list = await fetchResumeList(false);
if (!list.some((r) => r.id === resumeId)) {
  throw new Error(`Resume ${resumeId} not found; skip PDF download`);
}

Type guard

function isBlob(x: unknown): x is Blob {
  return typeof Blob !== 'undefined' && x instanceof Blob;
}

Try / catch

try {
  const blob = await downloadResumePdf(resumeId, settings, locale);
} catch (e) {
  if ((e as Error).message.includes('status 5')) {
    notifyUser('PDF generation failed on the server; try again later.');
  } else {
    notifyUser('Download failed: ' + (e as Error).message);
  }
}

Prevention

When it happens

Trigger: apiFetch(getResumePdfUrl(resumeId, settings, locale)) returns non-2xx: PDF render job failure on the backend (500), invalid settings/locale producing a 400, unknown resumeId (404), or auth rejection (401/403). Malformed query params for settings can also trigger a 422.

Common situations: Downloading a PDF for a resume whose content contains data the renderer cannot handle (500); passing a locale code the backend does not support; bookmarked/download URL reuse after the resume was deleted; expired session during a long builder session.

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/7a24cea10650bf4e. Report an issue: GitHub.