Mintplex-Labs/anything-llm · warning

File not found or access denied

Error message

File not found or access denied

What it means

Returned (HTTP 404) by GET /agent-skills/generated-files/:filename when findFileSource(filename, {user, isMultiUser}) returns null. findFileSource searches (1) workspace chats the requesting user can access under multi-user permissions, then (2) scheduled job runs (single-user mode only). Null means no accessible record references the file — it does not exist in any chat/job, or the current user lacks permission. The 404 deliberately conflates 'missing' and 'denied' to avoid leaking which files exist.

Source

Thrown at server/endpoints/agentFileServer.js:54

        if (!filename)
          return response.status(400).json({ error: "Filename is required" });

        // Validate filename format
        const parsed = createFilesLib.parseFilename(filename);
        if (!parsed) {
          return response
            .status(400)
            .json({ error: "Invalid filename format" });
        }

        // Find a chat or scheduled job run that references this file
        const fileSource = await findFileSource(filename, {
          user,
          isMultiUser: multiUserMode(response),
        });

        if (!fileSource) {
          return response.status(404).json({
            error: "File not found or access denied",
          });
        }

        // Retrieve the file from storage
        const fileData = await createFilesLib.getGeneratedFile(filename);
        if (!fileData) {
          return response
            .status(404)
            .json({ error: "File not found in storage" });
        }

        // Get mime type and set headers for download
        const mimeType = createFilesLib.getMimeType(`.${parsed.extension}`);
        const safeFilename = createFilesLib.sanitizeFilenameForHeader(
          fileSource.displayFilename || filename
        );
        response.setHeader("Content-Type", mimeType);

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Log in as the user who owns/participates in the chat that generated the file and copy the link from that chat
  2. Confirm your frontend talks to the same instance (same DB and storage) that generated the file
  3. Regenerate the artifact from a chat your user can access
  4. Operators: verify the workspace_chats / job-run records actually reference the filename before assuming a bug
Defensive patterns

Strategy: validation

Validate before calling

// Before sharing a link, confirm the current session can see its source chat
const me = await currentUser();
if (artifact.chatId && !me.accessibleChatIds.includes(artifact.chatId))
  throw new Error('this file belongs to a workspace you cannot access');

Try / catch

const res = await fetch(url, {credentials: 'include'});
if (res.status === 404) {
  // indistinguishable by design: missing OR denied —
  // re-authenticate as the owning user or regenerate the file
}

Prevention

When it happens

Trigger: In multi-user mode, requesting a file generated inside another user's workspace chat; using a filename from a different instance (frontend pointing at a backend with another database); the chat that referenced the file was deleted; the session resolves to a different/anonymous user than the one who generated it.

Common situations: Sharing artifact URLs between users (denied by design in multi-user mode); split frontend/backend environments with divergent data; stale links after workspace cleanup; login state confusion where the browser session belongs to a lesser-privileged account.

Understand the failure class

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/57501be947fe2eb4. Report an issue: GitHub.