unslothai/unsloth · error

Delete failed (${res.status})

Error message

Delete failed (${res.status})

What it means

Thrown by deletePromptEntry when DELETE /api/prompts/entries/:id returns non-2xx. Unlike save/bulk (which route through parseJsonOrThrow), the delete path has no body parsing — only the numeric status is reported. The entry therefore remains in local state.

Source

Thrown at studio/frontend/src/features/chat/api/prompts-api.ts:48

export async function listPromptEntries(): Promise<PromptEntry[]> {
  const res = await authFetch("/api/prompts/entries");
  const data = await parseJsonOrThrow<{ entries: PromptEntry[] }>(res);
  return data.entries;
}

export async function savePromptEntry(entry: PromptEntry): Promise<PromptEntry> {
  const res = await authFetch(`/api/prompts/entries/${entry.id}`, {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(entry),
  });
  return parseJsonOrThrow<PromptEntry>(res);
}

export async function deletePromptEntry(id: string): Promise<void> {
  const res = await authFetch(`/api/prompts/entries/${id}`, { method: "DELETE" });
  if (!res.ok) throw new Error(`Delete failed (${res.status})`);
}

export async function bulkSavePromptEntries(entries: PromptEntry[]): Promise<number> {
  if (!entries.length) return 0;
  const res = await authFetch("/api/prompts/entries/bulk", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ entries }),
  });
  const data = await parseJsonOrThrow<{ count: number }>(res);
  return data.count;
}

export async function listPromptLists(): Promise<PromptListEntry[]> {
  const res = await authFetch("/api/prompts/lists");
  const data = await parseJsonOrThrow<{ lists: PromptListEntry[] }>(res);
  return data.lists;
}

View on GitHub (pinned to 203007d190)

Solutions

  1. Re-auth if 401, retry after backend recovery if 5xx.
  2. On repeated failure, refresh the entries list and retry against fresh state.
  3. Consider treating 404 as success if the UX allows (pattern already used in providers deleteProviderConfig).

Example fix

// before
if (!res.ok) throw new Error(`Delete failed (${res.status})`);

// after
if (res.status === 404) return; // already deleted elsewhere
if (!res.ok) throw new Error(`Delete failed (${res.status})`);
Defensive patterns

Strategy: fallback

Try / catch

try { await deletePromptEntry(id); }
catch (e) {
  if (/\(404\)$/.test(e.message)) { removeEntryLocally(id); return; } // already gone
  showError(e.message);
}

Prevention

When it happens

Trigger: Deleting a prompt entry that is concurrently deleted elsewhere (non-404 error), deleting with expired auth (401), or backend failure (5xx).

Common situations: Two tabs deleting the same entry where the server does not return 404-or-2xx for the loser; session expired before the delete click; backend restart mid-operation.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/39c227e717011001. Report an issue: GitHub.