odysseus-dev/odysseus · error · Error
Failed to pause task
Error message
Failed to pause task
What it means
Thrown by _pauseTask (static/js/tasks.js:139) when POST /api/tasks/{id}/pause returns non-2xx; generic 'Failed to pause task' hides the status. Pause is a state transition on a live task, so failures cluster around the task's current lifecycle state rather than validation.
Source
Thrown at static/js/tasks.js:139
const existing = card.querySelector('.task-card-delete-busy');
if (!active) {
existing?.remove();
continue;
}
if (!existing) {
const badge = document.createElement('span');
badge.className = 'task-card-delete-busy';
badge.innerHTML = '<span class="task-card-delete-busy-label">Deleting</span><span class="task-card-delete-busy-spin" aria-hidden="true"></span>';
card.appendChild(badge);
}
}
}
async function _pauseTask(id) {
const res = await fetch(`${API_BASE}/api/tasks/${id}/pause`, {
method: 'POST', credentials: 'same-origin',
});
if (!res.ok) throw new Error('Failed to pause task');
}
async function _resumeTask(id) {
const res = await fetch(`${API_BASE}/api/tasks/${id}/resume`, {
method: 'POST', credentials: 'same-origin',
});
if (!res.ok) throw new Error('Failed to resume task');
}
async function _runNow(id, force = false) {
const res = await fetch(`${API_BASE}/api/tasks/${id}/run${force ? '?force=true' : ''}`, {
method: 'POST', credentials: 'same-origin',
});
if (!res.ok) {
// Surface the backend's actual reason — 409 means "already running",
// 404 task missing, etc. Previously every error rendered as the same
// generic "Failed to trigger task", which hid the cause.
let msg = `Failed to trigger task (${res.status})`;View on GitHub (pinned to f9235ebbf1)
Solutions
- On failure, re-fetch the task list and re-render — the card's state label will show the true current state (paused/running) and usually explains the rejection.
- Treat 'already paused' outcomes as success and sync UI state.
- Add the status to the error message: `\`Failed to pause task (HTTP ${res.status})\``.
- Re-login on 401; on 403 verify you own the task.
Example fix
// before
if (!res.ok) throw new Error('Failed to pause task');
// after
if (!res.ok) throw new Error(`Failed to pause task (HTTP ${res.status})`); Defensive patterns
Strategy: try-catch
Try / catch
try { await _pauseTask(id); } catch (err) { await refreshTasks(); // re-sync true state — most failures are state races showError(err.message); } Prevention
- After any pause failure, re-fetch the task list to see the real state before retrying.
- Include r.status in the error string.
- Disable the pause/resume toggle while a transition is in flight.
- Treat 'not pausable' (409) outcomes as a UI-state refresh, not a hard error.
When it happens
Trigger: Clicking pause on a running task: POST /api/tasks/{id}/pause. 404 task deleted; 409 when the task is not in a pausable state (already paused, mid-run lock); 403 non-owner; 401 expired session; 500 scheduler error.
Common situations: Pause clicked while the task is between runs or already paused from another tab; task deleted since the list rendered; ownership mismatch.
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/3f5ea73b5f2456bd.
Report an issue: GitHub.