NousResearch/hermes-agent · error

text || HTTP ${res.status}

Error message

text || HTTP ${res.status}

What it means

The image upload POST to /api/chat/image-upload returned a non-OK HTTP status. The error prefers the server's response body text (which usually carries the backend's own error message) and falls back to `HTTP <status>` only when the body is empty. This is the same pattern as the dashboard's generic authedFetch error, applied to the chat image endpoint.

Source

Thrown at web/src/lib/chatImagePaste.ts:156

  const file =
    blob instanceof File
      ? blob
      : new File([blob], filename, { type: mime });

  const dataUrl = await fileToDataUrl(file);
  const qs = profile ? `?profile=${encodeURIComponent(profile)}` : "";
  const res = await authedFetch(`/api/chat/image-upload${qs}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      data_url: dataUrl,
      filename,
    }),
  });

  if (!res.ok) {
    const text = await res.text().catch(() => res.statusText);
    throw new Error(text || `HTTP ${res.status}`);
  }

  const uploaded = (await res.json()) as ChatImageUploadResult;
  if (!uploaded?.path) {
    throw new Error("image upload did not return a path");
  }
  return uploaded;
}

View on GitHub (pinned to c896c09c42)

Solutions

  1. Read the server text in the error message — it usually names the exact backend cause (invalid data URL, payload too large, auth required).
  2. For 401: reload the dashboard to refresh auth, then paste again.
  3. For 413: raise the proxy's request body limit or send a smaller image (see the max-MB error).
  4. For 500: check gateway logs for the write failure (permissions/disk) in the upload target directory.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const { path } = await uploadChatImage(blob, profile)
} catch (err) {
  const msg = String(err)
  if (msg.startsWith('401') || msg.startsWith('403')) { location.reload(); return }
  if (msg.startsWith('413')) { toast('Image too large for the server'); return }
  toast(`Upload failed: ${msg}`)
}

Prevention

When it happens

Trigger: Uploading a data_url whose base64 is corrupt or whose mime is disallowed (400), uploading when the session expired (401), hitting a server-side body-size limit (413), or the gateway erroring while writing the upload to disk (500).

Common situations: Session cookie expired between page load and paste; reverse proxy (nginx/caddy) with a smaller client_max_body_size than the dashboard's limit; disk-full or permission errors in the gateway's upload directory.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/187bd343c81a2378. Report an issue: GitHub.