unslothai/unsloth · error · ChatSettingsRequestError

${parseErrorText(response.status, body)}

Error message

${parseErrorText(response.status, body)}

What it means

ChatSettingsRequestError (defined in settings-retry.ts) is thrown by parseJsonOrThrow in chat-settings-api.ts whenever a settings request returns non-2xx. Unlike a bare Error it carries response.status and the parsed detail, because the settings queue must distinguish 'server down' (keep the patch and retry later) from 'server rejects this body' (drop the offending fields). The message string itself is built by parseErrorText.

Source

Thrown at studio/frontend/src/features/chat/api/chat-settings-api.ts:109

  }
  if (
    body &&
    typeof body === "object" &&
    "message" in body &&
    typeof body.message === "string"
  ) {
    return body.message;
  }
  return `Request failed (${status})`;
}

async function parseJsonOrThrow<T>(response: Response): Promise<T> {
  const body = await response.json().catch(() => null);
  if (!response.ok) {
    // Typed, not a bare Error: the settings queue has to tell a server that is
    // down (keep the patch) from a server that refuses this body (drop the
    // offending fields), and that decision needs the status and the detail.
    throw new ChatSettingsRequestError(
      parseErrorText(response.status, body),
      response.status,
      body && typeof body === "object" && "detail" in body
        ? (body as { detail: unknown }).detail
        : null,
    );
  }
  return body as T;
}

export async function getChatSettings(): Promise<PersistedChatSettings> {
  const response = await authFetch("/api/chat/settings");
  const data = await parseJsonOrThrow<ChatSettingsResponse>(response);
  return data.settings;
}

export async function saveChatSettingsPatch(
  patch: PersistedChatSettings,

View on GitHub (pinned to 203007d190)

Solutions

  1. Handle the typed error: on 5xx/network statuses keep the patch queued and retry; on 422 read .detail and strip the rejected fields.
  2. If schema drift caused 422s, re-fetch settings and reconcile with the fresh server shape.
  3. Check the server is running for persistent 5xx.

Example fix

// before
catch (e) { /* cannot tell down from refused */ }

// after
import { ChatSettingsRequestError } from '../utils/settings-retry';
catch (e) {
  if (e instanceof ChatSettingsRequestError) {
    if (e.status >= 500 || e.status === 0) queueForRetry(patch);
    else dropFieldsNamedIn(e.detail);
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-sync reconciliation: fetch server settings before pushing a patch
const server = await getChatSettings();
patch = intersectKeys(patch, server); // drop fields the server no longer knows

Type guard

import { ChatSettingsRequestError } from '../utils/settings-retry';
export function isChatSettingsRequestError(e: unknown): e is ChatSettingsRequestError {
  return e instanceof ChatSettingsRequestError;
}

Try / catch

try { await pushSettings(patch); }
catch (e) {
  if (!isChatSettingsRequestError(e)) throw e;
  if (e.status >= 500) queuePatchForRetry(patch);   // server down: keep
  else dropFieldsInDetail(patch, e.detail);          // refused: prune
}

Prevention

When it happens

Trigger: Any failed GET/PUT of /api/chat/settings: server unreachable or 5xx (patch is kept for retry), or 422 with a detail describing which settings fields are invalid (fields get dropped).

Common situations: Backend restarted with a newer/older settings schema so stored client settings no longer validate; server briefly down while the queue flushes; auth expiry mid-sync.

Related errors


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