Mintplex-Labs/anything-llm · warning · Error

Cannot copy symbolic link: ${source}. Symlinks are not allow

Error message

Cannot copy symbolic link: ${source}. Symlinks are not allowed during copy operations.

What it means

Thrown by copyRecursive() in the filesystem copy-file plugin when fs.lstat() reports the source is a symbolic link. The tool deliberately refuses to traverse or copy symlinks as a security measure to prevent following links outside the allowed workspace. Because copyRecursive recurses into directories, a symlink nested anywhere inside a copied directory also triggers this.

Source

Thrown at server/utils/agents/aibitat/plugins/filesystem/copy-file.js:9

const fs = require("fs/promises");
const path = require("path");
const filesystem = require("./lib.js");

async function copyRecursive(source, destination) {
  const lstat = await fs.lstat(source);

  if (lstat.isSymbolicLink()) {
    throw new Error(
      `Cannot copy symbolic link: ${source}. Symlinks are not allowed during copy operations.`
    );
  }

  if (lstat.isDirectory()) {
    await fs.mkdir(destination, { recursive: true });
    const entries = await fs.readdir(source);
    for (const entry of entries) {
      await copyRecursive(
        path.join(source, entry),
        path.join(destination, entry)
      );
    }
  } else {
    await fs.copyFile(source, destination);
  }
}

View on GitHub (pinned to 526360e320)

Solutions

  1. Resolve the symlink to its real target before copying, then copy the resolved path (which itself must be within allowed directories).
  2. Exclude symlinked entries from the copy operation.
  3. Replace symlinks with real files if they must be copied.
  4. Copy individual real files rather than a directory containing symlinks.
Defensive patterns

Strategy: validation

Validate before calling

const fs = require("fs/promises");
async function assertNotSymlink(p) {
  const st = await fs.lstat(p);
  if (st.isSymbolicLink())
    throw new Error(`Refusing to copy symlink ${p}; resolve it first`);
}

Try / catch

// the tool handler already catches this and returns a string result;
// in custom callers, catch and resolve the link target instead
try { await copyRecursive(src, dst); }
catch (e) { if (e.message.includes("symbolic link")) { /* resolve real path */ } else throw e; }

Prevention

When it happens

Trigger: Calling the filesystem-copy-file tool where the source path, or any entry within a source directory, is a symbolic link. The error fires before any copy attempt for that entry. The handler catches it and returns the message as a string result to the agent rather than throwing to the caller.

Common situations: User workspace contains symlinks (e.g., linked node_modules, config shortcuts); copying a directory tree that includes linked files; an agent attempting to back up a folder with shortcuts.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13). Data as JSON: /api/errors/a2aa67b8e5a87203. Report an issue: GitHub.