multica-ai/multica · error · PreviewTooLargeError

attachment too large for inline preview

Error message

attachment too large for inline preview

What it means

Wrap thrown by prepareHermesHome when mountHermesMemories fails. With a memory store configured, the overlay's memories/ dir is linked at the agent's persistent store so memories survive the task; failure to establish the link is fatal because the alternative would silently lose the agent's memory contract.

Source

Thrown at packages/core/api/client.ts:2982

  // bypasses Content-Disposition: attachment for the `text/*` family, both
  // of which would otherwise prevent the renderer from getting the body.
  // The server always replies with `text/plain; charset=utf-8` for safety;
  // the original MIME ships back in the `X-Original-Content-Type` header so
  // the preview dispatcher can choose between markdown / html / plain code.
  //
  // Routes through `fetchRaw` so it inherits the standard auth headers,
  // 401 → handleUnauthorized recovery, request-id logging, and ApiError
  // shape. 413 / 415 are translated to typed `Preview*Error` instances so
  // the modal can render specific fallbacks instead of generic failure.
  async getAttachmentTextContent(
    id: string,
  ): Promise<{ text: string; originalContentType: string }> {
    let res: Response;
    try {
      res = await this.fetchRaw(`/api/attachments/${id}/content`);
    } catch (err) {
      if (err instanceof ApiError) {
        if (err.status === 413) throw new PreviewTooLargeError();
        if (err.status === 415) throw new PreviewUnsupportedError();
      }
      throw err;
    }
    return {
      text: await res.text(),
      originalContentType: res.headers.get("X-Original-Content-Type") ?? "",
    };
  }

  // Fetches the raw bytes of an attachment through the unified download
  // endpoint.
  //
  // This is the last-resort inline-media path for deployments where the
  // server has no natively-loadable URL to offer. `GET /api/attachments/{id}`
  // only upgrades `download_url` to a signed storage URL under CloudFront
  // signing or presign mode; in **proxy** mode (self-hosted MinIO or any
  // storage endpoint on an internal host, which the default `auto` mode

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Check that the memory store path exists, is a directory, and is writable by the daemon user.
  2. Clear the stale memories/ entry inside the per-task hermes-home and retry prepare.
  3. Recreate or re-provision the agent's memory store if it was deleted.
  4. Align filesystems: keep the store on the same filesystem as env-root if the mount uses links.
Defensive patterns

Strategy: validation

Validate before calling

if memoryStore != "" {
    fi, err := os.Stat(memoryStore)
    if err != nil || !fi.IsDir() {
        return fmt.Errorf("memory store missing or not a dir: %s", memoryStore)
    }
}

Try / catch

if err := prepareHermesHome(...); err != nil {
    if strings.Contains(err.Error(), "mount agent memories") {
        // repair/recreate the memory store dir, or disable memory persistence for this agent deliberately
    }
}

Prevention

When it happens

Trigger: prepareHermesHome is called with a non-empty memoryStore and mountHermesMemories(hermesHome, memoryStore, logger) errors — the store path is unusable (wrong type, unreadable, cross-filesystem link failure) or a conflicting memories/ entry already exists in the overlay.

Common situations: Memory store directory deleted or moved after the agent was created; store on NFS with permission issues; stale memories/ symlink left in a recycled env-root; store owned by a different daemon user.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/d478797317d32cef. Report an issue: GitHub.