odysseus-dev/odysseus · error · Error
HTTP ${r.status}
Error message
HTTP ${r.status} What it means
Thrown by _deleteNoteApi in notes.js when DELETE /api/notes/{id} returns non-ok. Per the inline comment this was deliberate: the function used to swallow 4xx/5xx, and now throws 'HTTP <status>' so callers can distinguish success from failure and toast accordingly.
Source
Thrown at static/js/notes.js:479
}
async function _saveNote(note) {
const method = note.id ? 'PUT' : 'POST';
const url = note.id ? `${API_BASE}/api/notes/${note.id}` : `${API_BASE}/api/notes`;
const res = await fetch(url, {
method, credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(note),
});
if (!res.ok) throw new Error('Failed to save note');
return await res.json();
}
async function _deleteNoteApi(id) {
// v2 review — used to swallow 4xx/5xx silently. Throw so callers can
// distinguish success vs failure and toast accordingly.
const r = await fetch(`${API_BASE}/api/notes/${id}`, { method: 'DELETE', credentials: 'same-origin' });
if (!r.ok) throw new Error('HTTP ' + r.status);
}
async function _patchNote(id, patch) {
const res = await fetch(`${API_BASE}/api/notes/${id}`, {
method: 'PUT', credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(patch),
});
if (!res.ok) throw new Error('Failed to update note');
return await res.json();
}
// ---- Helpers ----
function _esc(s) { return uiModule.esc ? uiModule.esc(s || '') : (s || '').replace(/</g, '<').replace(/>/g, '>'); }
function _attrEsc(s) {
return String(s || '')
.replace(/"/g, '"')View on GitHub (pinned to f9235ebbf1)
Solutions
- Treat 404 as success (note already gone) in the caller, then refresh the list.
- For 500, check write permissions on the notes storage backend.
- Reload the notes module to resync state and retry.
Example fix
// before
if (!r.ok) throw new Error('HTTP ' + r.status);
// after (idempotent delete)
if (!r.ok && r.status !== 404) throw new Error('HTTP ' + r.status); Defensive patterns
Strategy: try-catch
Try / catch
try { await _deleteNoteApi(id); } catch (e) { if (e.message.includes('404')) { /* already gone — treat as success */ } else { toast('Delete failed: ' + e.message); } } finally { refreshList(); } Prevention
- Treat delete-404 as idempotent success
- Always refresh the list after delete attempts regardless of outcome
- Keep throwing (per the v2 review comment) so callers decide policy
When it happens
Trigger: Deleting a note that was already deleted server-side (404); notes store file locked or unwritable (500); expired credentials (401).
Common situations: Double-clicking delete or having the same notes open in two tabs; server data reset while the UI list was cached.
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/1657fddec9616458.
Report an issue: GitHub.