odysseus-dev/odysseus · error · Error
Request failed (HTTP ${response.status})
Error message
Request failed (HTTP ${response.status}) What it means
Default message produced by _fetchJson in providerDeviceFlow.js when a device-flow HTTP call (start or poll) returns non-ok AND the response body carried no usable message. _messageFromPayload prefers detail then message from the parsed JSON; only when the body is empty/unparseable does the template literal with the status code become the message.
Source
Thrown at static/js/providerDeviceFlow.js:60
if (payload && typeof payload.message === 'string' && payload.message.trim()) {
return payload.message.trim();
}
return fallback;
}
export function formatDeviceFlowError(error, fallback = 'Request failed') {
if (!error) return fallback;
if (typeof error === 'string') return error;
if (error.detail) return String(error.detail);
if (error.message) return String(error.message);
return fallback;
}
async function _fetchJson(fetchImpl, url, options, fallback) {
const response = await fetchImpl(url, options);
const payload = await _jsonOrEmpty(response);
if (!response.ok) {
throw new Error(_messageFromPayload(payload, fallback || `Request failed (HTTP ${response.status})`));
}
return payload;
}
function _defaultSleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function _callCallback(fn, payload) {
if (typeof fn === 'function') await fn(payload);
}
export async function runProviderDeviceFlow(provider, options = {}) {
const cfg = PROVIDER_DEVICE_FLOWS[provider];
if (!cfg) throw new Error(`Unknown device-flow provider: ${provider}`);
const fetchImpl = options.fetchImpl || globalThis.fetch?.bind(globalThis);
if (!fetchImpl) throw new Error('Fetch API is unavailable');View on GitHub (pinned to f9235ebbf1)
Solutions
- Open devtools network tab and read the actual response body/status for the failed start or poll call.
- If a proxy is intercepting, fix the routing so /api/ reaches the app server.
- If 5xx with empty body, check app server logs for the crash behind it.
- Ensure credentials:'same-origin' cookie is present (log in to the app first).
Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof fetchImpl !== 'function') throw new Error('Fetch API is unavailable'); Type guard
const hasPayloadMessage = (p) => !!p && (typeof p.detail === 'string' || typeof p.message === 'string');
Try / catch
try { return await _fetchJson(fetchImpl, url, options, fallback); } catch (e) { return formatDeviceFlowError(e, `Request failed for ${url}`); } Prevention
- Always send JSON error bodies from the API so detail/message extraction works
- Keep the fallback string provider-specific for better UX
- Test device-flow endpoints through the same proxy path as production
When it happens
Trigger: POST to the provider's startUrl (e.g. /api/auth/{provider}/device/start) returning 500 with an empty body; poll endpoint returning 502 from a proxy with an HTML page that fails JSON parsing; CSRF/auth cookie missing so the server rejects with a bare 403.
Common situations: Reverse proxy (nginx) intercepting the API route and returning plain error pages; app server crashed and the static file server returned a 404 page; running the module in a test environment without a fetch stub (though missing fetch throws error 92 instead).
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/99d9b8a97a491fa0.
Report an issue: GitHub.