odysseus-dev/odysseus · warning · Error

data.error || 'failed'

Error message

data.error || 'failed'

What it means

Application-level error while staging an email attachment for forwarding: POST /api/email/compose-from-attachment/{uid}/{index} answered 200 but the JSON body has success falsy, so data.error (or 'failed') is thrown per attachment. Other attachments in the loop still attempt to stage; each failure shows a toast.

Source

Thrown at static/js/document.js:3177

    if (!doc || doc.language !== 'email') return;
    if (!fields?.forwardAttachments || !fields.sourceUid || !Array.isArray(fields.attachments) || fields.attachments.length === 0) return;
    const sourceKey = `${fields.sourceFolder || 'INBOX'}:${fields.sourceUid}:${fields.attachments.map(a => a.index).join(',')}`;
    if (doc._forwardedAttachmentSourceKey === sourceKey) return;
    doc._forwardedAttachmentSourceKey = sourceKey;
    if (!doc._composeAtts) doc._composeAtts = [];
    const existingForwarded = new Set(doc._composeAtts.filter(a => a.forwardedSourceKey === sourceKey).map(a => String(a.sourceIndex)));
    let added = 0;
    for (const att of fields.attachments) {
      const sourceIndex = String(att.index);
      if (existingForwarded.has(sourceIndex)) continue;
      try {
        const folderQs = encodeURIComponent(fields.sourceFolder || 'INBOX');
        const res = await fetch(`${API_BASE}/api/email/compose-from-attachment/${encodeURIComponent(fields.sourceUid)}/${encodeURIComponent(att.index)}?folder=${folderQs}`, {
          method: 'POST',
          credentials: 'same-origin',
        });
        const data = await res.json();
        if (!data.success) throw new Error(data.error || 'failed');
        doc._composeAtts.push({
          token: data.token,
          filename: data.filename || att.filename,
          size: data.size || att.size || 0,
          forwardedSourceKey: sourceKey,
          sourceIndex,
        });
        added += 1;
      } catch (err) {
        console.error('Failed to stage forwarded attachment:', err);
        if (uiModule) uiModule.showError(`Forward attachment failed: ${att.filename || 'attachment'}`);
      }
    }
    if (added) {
      _renderComposeAttachments();
      clearTimeout(_autoSaveDebounce);
      _autoSaveDebounce = setTimeout(() => { saveDocument({ silent: true }); }, 800);
    }

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Read data.error for the backend reason; usually the message is gone from the given folder
  2. Re-fetch/re-render the email document to refresh uid, folder, and attachment indices, then retry forward
  3. Ensure the folder query param matches the folder the message actually resides in
  4. Check backend temp storage health if errors mention tokens or disk
Defensive patterns

Strategy: validation

Validate before calling

if (!fields.sourceUid || !Array.isArray(fields.attachments)) { uiModule?.showError?.('Email data incomplete — reload the email'); return; }
if (!fields.sourceFolder) fields.sourceFolder = 'INBOX'; // be explicit about the default

Try / catch

for (const att of fields.attachments) {
  try {
    const res = await fetch(url, { method: 'POST', credentials: 'same-origin' });
    const data = await res.json().catch(() => ({}));
    if (!res.ok || !data.success) {
      console.warn(`Staging ${att.filename} failed:`, data.error || res.status);
      continue; // skip this attachment, keep staging the rest
    }
    doc._composeAtts.push({ token: data.token, /* ... */ });
    added += 1;
  } catch (err) {
    console.error('Failed to stage forwarded attachment:', err);
    if (uiModule) uiModule.showError(`Forward attachment failed: ${att.filename || 'attachment'}`);
  }
}

Prevention

When it happens

Trigger: 200 with {success:false,error:'message not found'} — the source uid was expunged or moved to another folder; attachment index stale after the message changed on the server; backend temp-token store full or unwritable.

Common situations: Message moved/deleted between opening the email and clicking forward; folder param defaulting to INBOX when the message lives elsewhere; backend cache directory permissions; concurrent forwarding of the same attachment.

Related errors


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