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

  1. Open devtools network tab and read the actual response body/status for the failed start or poll call.
  2. If a proxy is intercepting, fix the routing so /api/ reaches the app server.
  3. If 5xx with empty body, check app server logs for the crash behind it.
  4. 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

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.