odysseus-dev/odysseus · warning · Error

Server error ' + res.status

Error message

Server error ' + res.status

What it means

HTTP 404 from PUT /{file_id}/vision when the caller is authenticated but neither the file's owner nor an admin — the owner-or-admin gate on the write path. Returned as 404 to avoid leaking other users' files. It is the second 404 on this route: the first (index miss) fires earlier, so reaching this one means the file exists in uploads.json but belongs to someone else.

Source

Thrown at static/js/chat.js:6266

      }
    }

    if (!msgIds.length || !sessionId) {
      // No persisted rows to delete (no DB IDs, or no session at all — e.g. an
      // error output shown before a model was selected, #1428). Just remove the
      // DOM so the "x" works regardless.
      domToRemove.forEach(el => el.remove());
      if (uiModule) uiModule.showToast('Message deleted');
      return;
    }

    try {
      const res = await fetch(`${API_BASE}/api/session/${sessionId}/delete-messages`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ msg_ids: msgIds })
      });
      if (!res.ok) throw new Error('Server error ' + res.status);
      domToRemove.forEach(el => el.remove());
      if (uiModule) uiModule.showToast('Message deleted');
    } catch (err) {
      console.error('Delete failed:', err);
      if (uiModule) uiModule.showError('Delete failed: ' + err.message);
    }
  }

  /**
   * Edit an AI message inline. Makes the body contentEditable, saves to DB on confirm.
   */
  export async function editAIMessage(msgElement) {
    const body = msgElement.querySelector('.body');
    if (!body) return;

    const isEditing = body.contentEditable === 'true' || body.contentEditable === 'plaintext-only';
    if (isEditing) return; // already editing

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Save the OCR edit from the owning account (or an admin) — the UI should only expose the editor to the owner.
  2. Inspect uploads.json to confirm the owner if access should have worked; repair misattributed ownership after user renames/migrations.
  3. Return a clear 'read-only' state in the UI for files the current user doesn't own to prevent the failed save.
Defensive patterns

Strategy: validation

Validate before calling

const canEdit = (att, user) => !authConfigured || att.owner === user || user?.isAdmin;
if (!canEdit(att, currentUser)) renderReadOnly(att);

Try / catch

const r = await fetch(url, { method: 'PUT', credentials: 'include' });
if (r.status === 404) showNotEditable(att); // not owner — hide editor

Prevention

When it happens

Trigger: PUT /api/upload/{id}/vision as user B for a file whose index entry has owner=user A and B is not admin; ownership field changed by a migration so the editor no longer matches.

Common situations: Shared workstation/browser profile logged in as a different account; admin edited the file earlier, then a non-admin account tries to save over that edit.

Related errors


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