affaan-m/ECC · error · Error
request failed
Error message
request failed
What it means
Thrown by postWorkItem as a last-resort message when the control-pane POST responded with HTTP 200 and a JSON body whose result.ok is falsy, but result.error is empty/undefined. It means the server signaled failure (ok:false) without giving a reason, so the client cannot surface anything more specific than 'request failed'.
Source
Thrown at scripts/lib/control-pane/ui.js:664
}
$('#query-form').addEventListener('submit', event => {
event.preventDefault();
state.query = $('#query').value.trim();
load().catch(error => showError('#app', error));
});
$('#refresh').addEventListener('click', () => {
load().catch(error => showError('#app', error));
});
async function postWorkItem(pathSuffix, payload) {
const response = await fetch('/api/work-items/' + pathSuffix, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(payload || {})
});
const result = await readJsonResponse(response);
if (!result.ok) throw new Error(result.error || 'request failed');
await load();
}
window.eccClaimItem = function (id) {
if (!state.allowActions) return;
const owner = window.prompt('Claim "' + id + '" as (owner name):');
if (!owner) return;
const as = (window.prompt("Owner kind: 'agent' or 'human'", 'human') || '').trim().toLowerCase();
postWorkItem(encodeURIComponent(id) + '/claim', { owner: owner.trim(), as: as === 'agent' ? 'agent' : 'human' })
.catch(error => showError('#app', error));
};
window.eccMoveItem = function (id, lane) {
if (!state.allowActions) return;
postWorkItem(encodeURIComponent(id) + '/move', { lane })
.catch(error => showError('#app', error));
};
// Live board: refresh on a gentle interval; pause while a prompt/tab is hidden.View on GitHub (pinned to 01e15490f0)
Solutions
- On the server, always populate result.error (and result.reason) whenever ok is false so the client has something actionable.
- On the client, surface result.reason || result.error before falling back, and log the full result object for diagnosis.
- Reproduce with curl -X POST /api/work-items/<id>/<action> -H 'content-type: application/json' -d '{}' and inspect the JSON response.
- Check whether allowActions gating or another precondition returned ok:false intentionally.
Example fix
// before
if (!result.ok) throw new Error(result.error || 'request failed');
// after — surface any reason the server gave
if (!result.ok) {
const detail = result.error || result.reason || `request failed (${JSON.stringify(result)})`;
throw new Error(detail);
} Defensive patterns
Strategy: validation
Validate before calling
function assertOk(result) {
if (!result || result.ok === false) {
const detail = (result && (result.error || result.reason)) || 'request failed (no reason supplied)';
throw new Error(detail);
}
} Type guard
function isOkResult(result) {
return result && result.ok === true;
} Try / catch
try {
await postWorkItem(path, payload);
} catch (e) {
if (e.message === 'request failed') {
// server returned ok:false with no error; inspect network/response in devtools
}
throw e;
} Prevention
- Server-side: always set result.error (and result.reason) whenever ok is false.
- Client-side: surface result.reason || result.error before the generic fallback.
- Add a contract test asserting ok:false responses always include an error field.
When it happens
Trigger: A work-item mutation route (claim, move, etc.) returns { ok:false } with no error field; readJsonResponse passed because the body was valid JSON and response.ok was true, but the application-level success flag was false and the reason field was omitted.
Common situations: Server-side handler short-circuited (e.g. state.allowActions was false) and returned { ok:false } without populating error; a refactor changed the response shape from { error } to { reason } so the client's fallback kicks in; the route returns ok:false on a no-op but forgets to attach a message.
Related errors
- Expected JSON response from control pane:
- Unknown control-pane action: ${actionId}
- Invalid ${name} value: expected a path
- Invalid --port value: ${portValue}
- Config file not found: {path}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/bf00c68ee3ed8bc5.
Report an issue: GitHub.