odysseus-dev/odysseus · error · Error
HTTP ${res.status}${body ? ': ' + body.slice(0, 160) : ''}
Error message
HTTP ${res.status}${body ? ': ' + body.slice(0, 160) : ''} What it means
Thrown in markdown.js when adding a model endpoint via POST /api/model-endpoints fails. The first 160 chars of the response body are appended to the status. The button UI is restored and the error surfaced via showError in the catch, so the 'Add endpoint' affordance recovers cleanly.
Source
Thrown at static/js/markdown.js:1046
const parsed = new URL(baseUrl, window.location.origin);
const fd = new FormData();
fd.append('base_url', baseUrl);
fd.append('name', _endpointNameFromUrl(baseUrl));
fd.append('model_type', 'llm');
fd.append('endpoint_kind', 'auto');
fd.append('skip_probe', 'true');
if (/^(localhost|127\.0\.0\.1|0\.0\.0\.0)$/i.test(parsed.hostname)) {
fd.append('container_local', 'true');
}
const res = await fetch('/api/model-endpoints', {
method: 'POST',
credentials: 'same-origin',
body: fd,
});
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`HTTP ${res.status}${body ? ': ' + body.slice(0, 160) : ''}`);
}
btn.classList.add('added');
btn.innerHTML = '<span aria-hidden="true">✓</span><span>Added</span>';
window.dispatchEvent(new CustomEvent('ge:model-endpoints-updated', { detail: { baseUrl } }));
if (window.modelsModule?.refreshModels) await window.modelsModule.refreshModels(true);
if (window.sessionModule?.updateModelPicker) window.sessionModule.updateModelPicker();
uiModule.showToast?.(`Model endpoint added: ${_endpointNameFromUrl(baseUrl)}`);
} catch (err) {
btn.disabled = false;
btn.innerHTML = original;
uiModule.showError?.(`Add endpoint failed: ${err.message || err}`);
}
}
(function _watchModelEndpointLinks() {
if (window._modelEndpointLinkWatcherWired) return;
window._modelEndpointLinkWatcherWired = true;
View on GitHub (pinned to f9235ebbf1)
Solutions
- Verify the URL opens in a browser/curl from the same machine, including port and /v1 suffix if required.
- Read the truncated body text — FastAPI validation errors name the offending field.
- Remove the existing duplicate endpoint first if the server rejects re-registration.
- For Docker setups, use the container-reachable address (host.docker.internal or service name).
Defensive patterns
Strategy: validation
Validate before calling
let parsed; try { parsed = new URL(baseUrl); } catch { showError('Invalid URL'); return; }
if (!/^https?:$/.test(parsed.protocol)) { showError('Use http(s) URL'); return; } Type guard
const isEndpointPayload = (fd) => fd instanceof FormData && fd.get('base_url'); Try / catch
try { ... } catch (err) { btn.disabled = false; btn.innerHTML = original; uiModule.showError(`Add endpoint failed: ${err.message}`); } Prevention
- Validate URL shape client-side before POSTing
- Show the truncated body — it names the failing field
- Disable the button during flight and always restore it in catch
When it happens
Trigger: Submitting an endpoint URL that fails server-side validation (unreachable base URL even with skip_probe=true, malformed URL, duplicate endpoint); a provider value the backend rejects; container_local flag mismatch for localhost URLs.
Common situations: Adding an Ollama/LM Studio URL with wrong port or scheme; adding an endpoint that duplicates one already registered; pointing at a container-internal address without the container_local hint because the hostname regex did not match (e.g. host.docker.internal).
Related errors
- Failed to save signature
- Failed to create task
- Invalid SSH remote host
- Invalid remote_host — must be host or user@host, no SSH opti
- Invalid ssh_port
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/2b5568c69740f62e.
Report an issue: GitHub.