ruvnet/RuView · error · Error
Request failed
Error message
Request failed
What it means
api.service.js throws on any non-ok response, preferring the JSON body's `message` then `detail` fields. 'Request failed' is the last-resort message, used only when the body parsed as JSON but contains neither a truthy `message` nor `detail` — a non-JSON body instead produces the 'HTTP <status>: <statusText>' fallback from the catch.
Source
Thrown at ui/services/api.service.js:109
// An earlier revision caught the server's RFC 6750 "reauthentication
// required" challenge and redirected to /oauth/start. That challenge can
// never be issued to a browser: browser sign-in requests `sensing:read`
// only and always will (see BROWSER_SIGNIN_SCOPE), so no browser session
// holds `sensing:admin`, so the freshness gate the challenge announces is
// never reached. Admin work goes through the CLI or a pasted bearer.
//
// Removed rather than left inert, because it was not merely dead — it
// ended in a promise that never settles. If any other 401 ever grew that
// header, every caller awaiting this would hang forever with no error.
// The server-side guard stays as a fail-closed backstop; the client has
// nothing to do about a flow that does not exist.
// Handle errors
if (!processedResponse.ok) {
const error = await processedResponse.json().catch(() => ({
message: `HTTP ${processedResponse.status}: ${processedResponse.statusText}`
}));
throw new Error(error.message || error.detail || 'Request failed');
}
// Parse JSON response
const data = await processedResponse.json().catch(() => null);
return data;
} catch (error) {
// Only log if not a connection refusal (expected when DensePose API is down)
if (error.message && !error.message.includes('Failed to fetch')) {
console.error('API Request Error:', error);
}
throw error;
}
}
// GET request
async get(endpoint, params = {}, options = {}) {
const url = buildApiUrl(endpoint, params);View on GitHub (pinned to 4685618388)
Solutions
- Make the server's non-2xx responses include `message` or `detail` (FastAPI's default) so real text surfaces.
- Patch the fallback to carry status context: error.message || error.detail || `Request failed (HTTP ${processedResponse.status})`.
- When triaging, log processedResponse.status and the raw body to identify which endpoint and envelope shape is involved.
Example fix
// before (ui/services/api.service.js)
throw new Error(error.message || error.detail || 'Request failed');
// after
throw new Error(error.message || error.detail || `Request failed (HTTP ${processedResponse.status} ${processedResponse.statusText})`); Defensive patterns
Strategy: try-catch
Try / catch
try {
const data = await apiService.request('/zones', { method: 'GET' });
} catch (error) {
if (error.message === 'Request failed') {
// body had no message/detail; surface generic failure with endpoint context
console.error('Unstructured error response from /zones');
} else if (error.message?.includes('Failed to fetch')) {
// DensePose API down / network refused — expected condition
}
throw error;
} Prevention
- Make backend error responses include `message` or `detail` so this fallback never fires.
- Distinguish network refusals ('Failed to fetch') from server-side failures in catch blocks.
- Log the HTTP status alongside the message when triaging unstructured error bodies.
When it happens
Trigger: Backend or gateway returns non-2xx with a JSON body like {"error":"..."}, {"status":500}, or {"message":""} — envelopes this service does not recognize.
Common situations: Reverse proxies returning JSON errors in their own envelope; a framework version change moving the error text to a different key; production error sanitizers emptying message strings.
Related errors
- status ${resp.status}
- Failed to create stream: {response.status}
- Invalid settings file format
- Invalid stream options: ${validationResult.errors.join(', ')
- No active stream connection to reconnect
AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16).
Data as JSON: /api/errors/a881e4ce94734251.
Report an issue: GitHub.