srbhr/Resume-Matcher · error · Error

${message = errBody.detail or Failed to update feature promp

Error message

${message = errBody.detail or Failed to update feature prompts (status ${res.status}).}

What it means

The generic branch of updateFeaturePrompts: for any non-422-missing_placeholders failure it builds a message from errBody.detail — string detail used as-is, object detail JSON.stringify'd (avoiding '[object Object]'), and this exact message as the final fallback when the body has no usable detail. It then throws a plain Error. It fires for auth failures, other 422 validation errors, 404 routing problems, and 5xx backend faults on PUT /config/feature-prompts.

Source

Thrown at apps/frontend/lib/api/config.ts:407

    if (
      res.status === 422 &&
      typeof errBody.detail === 'object' &&
      errBody.detail?.code === 'missing_placeholders'
    ) {
      throw new FeaturePromptsError(errBody.detail);
    }
    // FastAPI can return ``detail`` as a string or a structured object.
    // Stringifying an object via the ``||`` shortcut yields "[object Object]";
    // serialize explicitly.
    let message: string;
    if (typeof errBody.detail === 'string') {
      message = errBody.detail;
    } else if (errBody.detail) {
      message = JSON.stringify(errBody.detail);
    } else {
      message = `Failed to update feature prompts (status ${res.status}).`;
    }
    throw new Error(message);
  }

  // Success path: require a valid JSON body. Swallowing parse errors here
  // would let an invalid success response be returned as FeaturePrompts
  // with undefined fields — caller code would then read .cover_letter_prompt
  // and get surprising behavior. Let the parse error propagate.
  return (await res.json()) as FeaturePrompts;
}

// API Key Management types
export type ApiKeyProvider =
  | 'openai'
  | 'azure_foundry'
  | 'anthropic'
  | 'google'
  | 'openrouter'
  | 'deepseek'
  | 'groq'

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Inspect the thrown message: a string detail is the backend's own explanation; a JSON-stringified object contains structured validation info; the fallback text means inspect res.status via logs/network tab.
  2. 401/403 → re-authenticate; 404 → fix BACKEND_ORIGIN/next.config.ts rewrites; 5xx → check backend logs.
  3. For object details, parse the JSON in the message to locate the offending field and correct the FeaturePromptsUpdate payload.
  4. Wrap the `fresh` refresh/save flow in try/catch so the error is displayed in the form rather than crashing the settings page.

Example fix

// before
await updateFeaturePrompts(update);

// after
try {
  await updateFeaturePrompts(update);
} catch (e) {
  if (e instanceof FeaturePromptsError) {
    showPlaceholderHints(e.detail);
  } else {
    showSaveError(e instanceof Error ? e.message : String(e));
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isNonEmptyPromptUpdate(u: FeaturePromptsUpdate): boolean {
  return Object.values(u).every((v) => typeof v === 'string' && v.trim().length > 0);
}

Type guard

function hasStringDetail(x: unknown): x is { detail: string } {
  return typeof x === 'object' && x !== null && typeof (x as any).detail === 'string';
}

Try / catch

try {
  await updateFeaturePrompts(update);
} catch (e) {
  if (e instanceof FeaturePromptsError) handlePlaceholders(e.detail);
  else showError(e instanceof Error ? e.message : 'Unknown save failure');
}

Prevention

When it happens

Trigger: Non-ok response on POST/PUT /config/feature-prompts that isn't the 422 missing_placeholders case: 401/403 (session expired, CSRF), 422 with a different validation code, 404 (endpoint absent / proxy misroute), 500/502 (backend down or failed persisting prompts).

Common situations: Saving feature prompts after the auth cookie expired; deploying mismatched frontend/backend versions so the endpoint moved; infrastructure outage returning an HTML error page (res.json() catch yields {}, so the fallback text shows).

Related errors


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