srbhr/Resume-Matcher · error · Error

${data.detail || Failed to update feature config (status ${r

Error message

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

What it means

updateFeatureConfig PUTs the feature configuration to /config/features and throws an Error on non-OK responses, preferring the backend's JSON `detail` field (FastAPI validation message) and falling back to a generic status-message string when the body cannot be parsed.

Source

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

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

  return res.json();
}

// Update feature configuration
export async function updateFeatureConfig(config: FeatureConfigUpdate): Promise<FeatureConfig> {
  const res = await apiFetch('/config/features', {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(config),
  });

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

  return res.json();
}

// Language configuration types
export type SupportedLanguage = 'en' | 'es' | 'zh' | 'ja' | 'pt' | 'fr' | 'ko';

export interface LanguageConfig {
  ui_language: SupportedLanguage;
  content_language: SupportedLanguage;
  supported_languages: SupportedLanguage[];
}

export interface LanguageConfigUpdate {
  ui_language?: SupportedLanguage;
  content_language?: SupportedLanguage;
}

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. Read the `detail` in the thrown message — it names the offending field/value; align the submitted FeatureConfig with the backend schema
  2. Re-login if status is 401/403
  3. Ensure frontend and backend versions match so the feature schema is identical
  4. Check backend logs for 500 persistence errors

Example fix

// before
await updateFeatureConfig({ enableX: 'yes' }); // 422: enableX expected boolean
// after
await updateFeatureConfig({ enableX: true });
Defensive patterns

Strategy: validation

Validate before calling

function validateFeatureConfig(c: Record<string, unknown>, schema: Record<string, 'boolean' | 'string' | 'number'>): string | null {
  for (const [k, t] of Object.entries(schema)) {
    const v = c[k];
    if (v === undefined) return `missing key: ${k}`;
    if (t === 'boolean' && typeof v !== 'boolean') return `${k} must be boolean`;
    if (t === 'number' && typeof v !== 'number') return `${k} must be number`;
  }
  return null;
}

Type guard

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

Try / catch

try {
  await updateFeatureConfig(config);
} catch (e) {
  showToast(e instanceof Error ? e.message : 'Feature config save failed'); // message carries backend detail
}

Prevention

When it happens

Trigger: Saving feature toggles when the backend rejects them: 422 schema validation (unknown/missing feature keys or wrong types after a frontend/backend version skew), 401 session expired, 500 persistence failure.

Common situations: Frontend and backend deployed at different versions so the feature-flag schema no longer matches; user's session expired while editing; concurrent config writes causing a backend conflict.

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