srbhr/Resume-Matcher · error · Error

Upload failed with status ${res.status}

Error message

Upload failed with status ${res.status}

What it means

uploadJobDescriptions in apps/frontend/lib/api/resume.ts throws this terse Error when the POST to `/jobs/upload` returns a non-OK status, including only the numeric status code (no response body). It indicates the backend rejected the batch of job descriptions or failed while creating the job record; diagnosing requires inspecting the network tab or backend logs since the message omits details.

Source

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

  try {
    return JSON.parse(text) as ImprovedResult;
  } catch (parseError) {
    console.error('Failed to parse improve response:', parseError, 'Raw response:', text);
    throw parseError;
  }
}

/** Uploads job descriptions and returns a job_id */
export async function uploadJobDescriptions(
  descriptions: string[],
  resumeId: string
): Promise<string> {
  const res = await apiPost('/jobs/upload', {
    job_descriptions: descriptions,
    resume_id: resumeId,
  });
  if (!res.ok) throw new Error(`Upload failed with status ${res.status}`);
  const data = await res.json();
  return data.job_id[0];
}

/** Improves the resume and returns the full preview object */
export async function improveResume(
  resumeId: string,
  jobId: string,
  promptId?: string
): Promise<ImprovedResult> {
  return postImprove('/resumes/improve', {
    resume_id: resumeId,
    job_id: jobId,
    prompt_id: promptId ?? null,
  });
}

/** Previews the resume improvement without saving */

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Reproduce in the browser network tab to read the response body, since this message omits it; classify 401/404/413/422/5xx.
  2. Validate before calling: descriptions is a non-empty array of non-empty strings and resumeId is a non-empty ID.
  3. For 413, chunk the upload into smaller batches or raise the backend body-size limit.
  4. For 401, re-authenticate and retry; for 404, verify the resume exists.
  5. For 5xx, check backend logs for job-creation/storage errors.

Example fix

// before
const res = await apiPost('/jobs/upload', {
  job_descriptions: descriptions,
  resume_id: resumeId,
});
if (!res.ok) throw new Error(`Upload failed with status ${res.status}`);
// after
if (!Array.isArray(descriptions) || descriptions.length === 0) {
  throw new Error('Provide at least one job description to upload.');
}
const res = await apiPost('/jobs/upload', {
  job_descriptions: descriptions,
  resume_id: resumeId,
});
if (!res.ok) {
  const data = await res.json().catch(() => ({}));
  throw new Error(data.detail || `Upload failed with status ${res.status}`);
}
Defensive patterns

Strategy: validation

Validate before calling

const cleaned = (descriptions ?? []).map(d => (d ?? '').trim()).filter(Boolean);
if (cleaned.length === 0) throw new Error('Provide at least one non-empty job description.');
if (!resumeId?.trim()) throw new Error('resumeId is required to upload job descriptions.');

Type guard

function hasUploadableDescriptions(v: unknown): v is string[] {
  return Array.isArray(v) && v.length > 0 &&
    v.every(d => typeof d === 'string' && d.trim().length > 0);
}

Try / catch

try {
  const jobId = await uploadJobDescriptions(descriptions, resumeId);
} catch (e) {
  const msg = e instanceof Error ? e.message : '';
  if (msg.includes('status 413')) showError('Too much content — upload fewer or shorter descriptions.');
  else if (msg.includes('status 401')) redirectToLogin();
  else showError('Upload failed. Please retry.');
}

Prevention

When it happens

Trigger: apiPost('/jobs/upload', { job_descriptions: descriptions, resume_id: resumeId }) resolves with res.ok === false: 401 unauthenticated, 404 resume_id not found, 422 empty descriptions array or items exceeding size/count limits, 413 payload too large, or 5xx backend storage/processing failure.

Common situations: Pasting very large or many job descriptions exceeds the request body limit (413); descriptions array is empty because scraping/parsing yielded nothing (422); resumeId references a deleted resume (404); auth cookie expired (401).

Related errors


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