srbhr/Resume-Matcher · error · Error

${data.detail || Failed to delete API key (status ${res.stat

Error message

${data.detail || Failed to delete API key (status ${res.status}).}

What it means

deleteApiKey issues DELETE for one provider's key on /config/api-keys and throws this when the response is not ok, preferring the backend `detail` string and falling back to the status-code message. It has no return value, so the throw is the only failure signal to handleDeleteApiKey.

Source

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

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

  return res.json();
}

// Delete API key for a specific provider
export async function deleteApiKey(provider: ApiKeyProvider): Promise<void> {
  const res = await apiFetch(`/config/api-keys/${provider}`, {
    method: 'DELETE',
    credentials: 'include',
  });

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

// Clear all API keys
export async function clearAllApiKeys(): Promise<void> {
  const res = await apiFetch('/config/api-keys?confirm=CLEAR_ALL_KEYS', {
    method: 'DELETE',
    credentials: 'include',
  });

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

// Reset database
export async function resetDatabase(): Promise<void> {

View on GitHub (pinned to 116f9cc3b0)

Solutions

  1. 404 → treat as 'already deleted' or verify the provider id matches PROVIDER_INFO and the deployed backend's enum.
  2. 401/403 → re-authenticate and retry; 5xx → check backend logs for key-store errors.
  3. Catch in handleDeleteApiKey, show the detail message, then refresh the key-status list so the UI matches server state.
  4. Avoid double-clicking delete: disable the button while the request is in flight to prevent duplicate 404s.

Example fix

// before
await deleteApiKey(provider);
refreshKeys();

// after
try {
  await deleteApiKey(provider);
} catch (e) {
  showToast(e instanceof Error ? e.message : 'Delete failed');
} finally {
  refreshKeys();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!SUPPORTED.includes(provider)) {
  throw new Error(`Unknown provider: ${provider}`);
}

Type guard

function is deletableProvider(p: string): boolean {
  return SUPPORTED.includes(p);
}

Try / catch

try {
  await deleteApiKey(provider);
} catch (e) {
  const msg = e instanceof Error ? e.message : '';
  if (msg.includes('status 404')) {
    showToast('Key was already removed');
  } else {
    showToast(msg || 'Delete failed');
  }
} finally {
  refreshKeys();
}

Prevention

When it happens

Trigger: Non-2xx on DELETE /config/api-keys/<provider>: 401/403 (expired session/CSRF), 404 (the provider has no stored key, or the route/provider id is unknown — mismatched frontend/backend provider enums), 422 (malformed provider identifier), 500 (key-store deletion failed).

Common situations: Deleting a key that was already removed in another tab (404); session expired between page load and the delete click; backend upgrade renamed a provider slug; DB lock preventing the delete.

Related errors


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