srbhr/Resume-Matcher · error · Error

Resume ID is required.

Error message

Resume ID is required.

What it means

normalizeResumeId in apps/frontend/lib/api/resume.ts throws this synchronous Error when the supplied resumeId is empty or contains only whitespace after trimming. It is a client-side input guard used before every resume API call in this module, preventing pointless network requests with an invalid path parameter.

Source

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

  resume_id: string;
  processing_status: 'pending' | 'processing' | 'ready' | 'failed';
  is_master: boolean;
}

interface ImproveResumeConfirmRequest {
  resume_id: string;
  job_id: string;
  improved_data: ResumeData;
  improvements: Array<{
    suggestion: string;
    lineNumber?: number | null;
  }>;
}

function normalizeResumeId(resumeId: string): string {
  const normalized = resumeId.trim();
  if (!normalized) {
    throw new Error('Resume ID is required.');
  }
  return normalized;
}

export interface ResumeListItem {
  resume_id: string;
  filename: string | null;
  is_master: boolean;
  parent_id: string | null;
  processing_status: 'pending' | 'processing' | 'ready' | 'failed';
  created_at: string;
  updated_at: string;
  title?: string | null;
  // Optional lightweight snippet of associated job description (populated client-side)
  jobSnippet?: string;
}

async function postImprove(

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Check where the resumeId comes from (router params, query string, state) and confirm it is populated before invoking the API.
  2. Gate the API call behind a loading/ready flag so it only runs once the ID is available.
  3. Trim and truthiness-check the ID at the call site and show a user-facing 'resume not selected' state instead of calling the API.
  4. Fix the data source that produced the empty ID (missing route param, empty localStorage entry).

Example fix

// before
useEffect(() => {
  getResume(resumeId).then(setResume);
}, [resumeId]);
// after
useEffect(() => {
  if (!resumeId?.trim()) return;
  getResume(resumeId).then(setResume);
}, [resumeId]);
Defensive patterns

Strategy: validation

Validate before calling

const id = (resumeId ?? '').trim();
if (!id) {
  // skip the API call and render an empty/redirect state
  return null;
}

Type guard

function isValidResumeId(v: unknown): v is string {
  return typeof v === 'string' && v.trim().length > 0;
}

Try / catch

try {
  const resume = await getResume(resumeId);
} catch (e) {
  if (e instanceof Error && e.message === 'Resume ID is required.') {
    showError('No resume selected. Please choose a resume first.');
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling any resume API function (getResume, improveResume, uploadJobDescriptions, etc.) with resumeId = '' , ' ', or an undefined/null value coerced to an empty string — typically because state had not loaded yet or a route param was missing.

Common situations: A React component renders and fires the API call before the resume ID is fetched from the router/query; a deep link is missing the id query parameter; localStorage held an empty value after a cleared session; copy-paste dropped the ID.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — 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/f7092b8377e9eac6. Report an issue: GitHub.