odysseus-dev/odysseus · warning · Error
data.error || ('HTTP ' + (data.status || 500))
Error message
data.error || ('HTTP ' + (data.status || 500)) What it means
HTTP 400 from POST /webhooks when the `name` form field, after strip() and truncation to MAX_NAME_LEN (100), is empty — i.e. missing, only whitespace, or a name composed solely of characters cut off by the 100-char truncation edge case. This is the first validation on webhook creation, before URL and events checks.
Source
Thrown at static/js/chat.js:6441
let newText = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const payload = line.slice(6).trim();
if (payload === '[DONE]') continue;
try {
const data = JSON.parse(payload);
// The endpoint streams `event: error\ndata: {error,status}` on
// failure — surface it instead of silently hanging on "Rewriting…".
if (data.error) {
throw new Error(data.error || ('HTTP ' + (data.status || 500)));
}
// Reasoning tokens (vLLM --reasoning-parser: Qwen3 / DeepSeek-R1)
// arrive as separate {delta, thinking:true} chunks. They are NOT
// the rewrite — fold them away so they don't pollute the result.
if (data.thinking) continue;
if (data.delta) {
newText += data.delta;
_killRwSpin();
if (bodyEl) {
bodyEl.innerHTML = markdownModule.processWithThinking(
markdownModule.squashOutsideCode(newText)
);
}
}
} catch (e) {
if (e instanceof Error && e.message) throw e; // re-throw real errors
/* ignore JSON parse noise */
}View on GitHub (pinned to f9235ebbf1)
Solutions
- Include a non-empty `name` form field (1–100 chars) in the request.
- Ensure the field is sent as form data, not JSON — the parameters are Form('') so a JSON body yields defaults.
- Trim the name client-side and reject empty before submitting.
- Check for stray field-name typos (name vs title/label) in the client.
Example fix
# before
curl -X POST url/api/webhooks -H 'Content-Type: application/json' -d '{"url": "https://x.example/hook"}'
# after
curl -X POST url/api/webhooks -F 'name=deploy hook' -F 'url=https://x.example/hook' -F 'events=message.created' Defensive patterns
Strategy: validation
Validate before calling
const name = (rawName ?? '').trim();
if (!name) return alert('Webhook name is required');
const fd = new FormData();
fd.set('name', name); // plus url, events, secret
await fetch('/api/webhooks', { method: 'POST', body: fd }); Type guard
function isCreatableWebhook(f: { name?: unknown }): boolean {
return typeof f.name === 'string' && f.name.trim().length > 0 && f.name.trim().length <= 100;
} Try / catch
const r = await fetch('/api/webhooks', { method: 'POST', body: fd });
if (r.status === 400) showFormError(await r.text()); // message names the failing field Prevention
- Send form fields (multipart/urlencoded), not JSON — the route binds Form parameters
- Require a non-empty trimmed name in the UI before submit
- Keep names within 100 characters (MAX_NAME_LEN)
When it happens
Trigger: POST /webhooks (multipart/form or urlencoded) with name omitted, name=" ", or name="" — for example a curl call using -d that drops an empty field, or a UI form submitted before the name input was filled.
Common situations: Form field named differently than expected (e.g. 'label' instead of 'name') so FastAPI binds the default ''; client sends JSON body while the route expects Form fields; automated scripts creating webhooks from a config where one entry lacks a name.
Related errors
- model returned no rewritten text
- Action '{task.action}' requires admin privileges
- await res.text()
- HTTP ${res.status}
- errData.detail || 'Failed to create session'
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/857a7156d6d70976.
Report an issue: GitHub.