odysseus-dev/odysseus · error · Error

Failed to revert task

Error message

Failed to revert task

What it means

Thrown when POST /api/tasks/{id}/revert (revert a built-in task to defaults) returns a non-2xx status. Unlike other calls in this module it does not parse the response body at all, so the backend's actual reason is always discarded and shown to the user as the generic message via showError.

Source

Thrown at static/js/tasks.js:1914

    : confirm('Delete this task and all its run history?');
  if (!ok) return;
  try {
    await _deleteTask(id);
    await _animateTaskRemoval([id]);
    if (uiModule) uiModule.showToast('Task deleted');
    await _fetchTasks();
    _renderMainView();
  } catch (e) { if (uiModule) uiModule.showError(e.message); }
}

async function _doRevert(id) {
  const ok = uiModule?.styledConfirm
    ? await uiModule.styledConfirm('Revert this built-in task to its default schedule and settings?', { confirmText: 'Revert' })
    : confirm('Revert this built-in task to its default?');
  if (!ok) return;
  try {
    const res = await fetch(`${API_BASE}/api/tasks/${id}/revert`, { method: 'POST', credentials: 'same-origin' });
    if (!res.ok) throw new Error('Failed to revert task');
    if (uiModule) uiModule.showToast('Reverted to default');
    await _fetchTasks();
    _renderMainView();
  } catch (e) { if (uiModule) uiModule.showError(e.message); }
}

async function _doClearTaskCache(id, label = 'cache') {
  const ok = uiModule?.styledConfirm
    ? await uiModule.styledConfirm(`Clear cached ${label} for this task?`, { confirmText: 'Clear' })
    : confirm(`Clear cached ${label} for this task?`);
  if (!ok) return;
  try {
    const res = await fetch(`${API_BASE}/api/tasks/${encodeURIComponent(id)}/clear-cache`, {
      method: 'POST',
      credentials: 'same-origin',
    });
    const data = await res.json().catch(() => ({}));
    if (!res.ok || !data.ok) throw new Error(data.detail || data.error || `HTTP ${res.status}`);

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Check the network tab for the real status code of the /revert call — the UI message hides it
  2. Only show the Revert action for tasks flagged as built-in/customized in GET /api/tasks
  3. Refresh the task list and retry; re-login on 401/403
  4. Improve the handler to parse res.json() detail like _doClearTaskCache does

Example fix

// before
const res = await fetch(`${API_BASE}/api/tasks/${id}/revert`, { method: 'POST', credentials: 'same-origin' });
if (!res.ok) throw new Error('Failed to revert task');
// after
const res = await fetch(`${API_BASE}/api/tasks/${id}/revert`, { method: 'POST', credentials: 'same-origin' });
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data.detail || `Failed to revert task (${res.status})`);
Defensive patterns

Strategy: try-catch

Validate before calling

const t = _tasks.find(x => x.id === id);
if (!t || !t.is_builtin && !t.customized) { showToast('Nothing to revert'); return; }

Try / catch

try { await _doRevert(id); } catch (e) { uiModule?.showError(e.message || 'Revert failed'); await _fetchTasks(); }

Prevention

When it happens

Trigger: Clicking Revert (after confirming) on a task that is not a built-in/customized task (404/400), on a task whose defaults cannot be restored server-side (500), or with an expired session (401/403).

Common situations: Revert offered in the UI for tasks that have no default definition on the server; server task definitions updated between page load and revert; auth cookie expired.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/ddd0b24c6aeb5ebd. Report an issue: GitHub.