srbhr/Resume-Matcher · error · Error

${data.detail || Failed to update prompt config (status ${re

Error message

${data.detail || Failed to update prompt config (status ${res.status}).}

What it means

updatePromptConfig (PUT/POST to /config/prompts) throws this when the response is not ok. It first tries res.json() to extract a backend `detail` message (FastAPI convention) and falls back to the generic status-code message if the body isn't JSON. So the message is either the server's explanation or 'Failed to update prompt config (status N).' Note the `||` shortcut: an object `detail` would stringify badly — for structured details prefer explicit serialization.

Source

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

  if (!res.ok) {
    throw new Error(`Failed to load prompt config (status ${res.status}).`);
  }

  return res.json();
}

// Update prompt configuration
export async function updatePromptConfig(update: PromptConfigUpdate): Promise<PromptConfig> {
  const res = await apiFetch('/config/prompts', {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(update),
  });

  if (!res.ok) {
    const data = await res.json().catch(() => ({}));
    throw new Error(data.detail || `Failed to update prompt config (status ${res.status}).`);
  }

  return res.json();
}

// Custom feature prompts (cover letter, cold outreach)
export interface FeaturePrompts {
  cover_letter_prompt: string;
  outreach_message_prompt: string;
  cover_letter_default: string;
  outreach_message_default: string;
}

export interface FeaturePromptsUpdate {
  cover_letter_prompt?: string;
  outreach_message_prompt?: string;
}

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Read the surfaced `detail` (or status code): 422 → fix the payload to match the backend PromptConfigUpdate schema; 401/403 → re-authenticate and retry; 5xx → check backend logs.
  2. Verify the update object only contains fields the backend accepts (provider, model, api_key, api_base, reasoning_effort etc.) after any API version change.
  3. Confirm the Next.js proxy rewrite for /api targets the running backend origin.
  4. Wrap the call in try/catch in the calling handler (e.g. `updated`) and show the message in the UI instead of letting it bubble as an unhandled rejection.

Example fix

// before
await updatePromptConfig(update);

// after
try {
  await updatePromptConfig(update);
} catch (e) {
  setSaveError(e instanceof Error ? e.message : 'Unknown error saving prompt config');
}
Defensive patterns

Strategy: try-catch

Validate before calling

const allowedKeys = ['provider', 'model', 'api_key', 'api_base', 'reasoning_effort'];
if (Object.keys(update).some((k) => !allowedKeys.includes(k))) {
  throw new Error('PromptConfigUpdate contains unknown fields');
}

Type guard

function isRecord(x: unknown): x is Record<string, unknown> {
  return typeof x === 'object' && x !== null && !Array.isArray(x);
}

Try / catch

try {
  await updatePromptConfig(update);
} catch (e) {
  const msg = e instanceof Error ? e.message : String(e);
  setSaveError(/status 4\d\d/.test(msg) ? 'Check your session and input, then retry.' : msg);
}

Prevention

When it happens

Trigger: Non-2xx response from the prompt-config update endpoint: 401/403 (expired session cookie, CSRF failure), 422 (FastAPI validation rejected the PromptConfigUpdate payload, e.g. invalid field value), 404 (route missing/misconfigured proxy), 500 (backend failed persisting config).

Common situations: Submitting the settings form after the session expired; sending an update shape that no longer matches the backend Pydantic schema after a version upgrade; backend temporarily down during save; proxy misroute returning an HTML 404 page (then data.detail is undefined and the fallback message shows).

Related errors


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