{"record":{"id":"0e04a89c6e8f5128","repo":"stablyai/orca","slug":"symlink-not-allowed-in-entry-name","errorCode":null,"errorMessage":"Symlink not allowed in '${entry.name}'","messagePattern":"Symlink not allowed in '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/filesystem-mutations.ts","lineNumber":695,"sourceCode":"    }\n  }\n  return false\n}\n\n/**\n * Recursively copy a directory and all its contents. Uses copyFile for\n * individual files to leverage native OS copy primitives instead of\n * buffering entire files into memory.\n */\nasync function recursiveCopyDir(srcDir: string, destDir: string): Promise<void> {\n  await mkdir(destDir, { recursive: false })\n  const entries = await readdir(srcDir, { withFileTypes: true })\n  for (const entry of entries) {\n    const srcPath = join(srcDir, entry.name)\n    const dstPath = join(destDir, entry.name)\n    const statResult = await lstat(srcPath)\n    if (statResult.isSymbolicLink()) {\n      throw new Error(`Symlink not allowed in '${entry.name}'`)\n    }\n    if (statResult.isDirectory()) {\n      await recursiveCopyDir(srcPath, dstPath)\n      continue\n    }\n    if (!statResult.isFile()) {\n      throw new Error(`Unsupported file type in '${entry.name}'`)\n    }\n    await copyLocalFileNoFollow(srcPath, dstPath, statResult)\n  }\n}\n\nasync function copyLocalFileNoFollow(\n  srcPath: string,\n  dstPath: string,\n  statResult?: Awaited<ReturnType<typeof lstat>>\n): Promise<void> {\n  const beforeOpenStat = statResult ?? (await lstat(srcPath))","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/filesystem-mutations.ts#L677-L713","documentation":"Thrown in recursiveCopyDir during local external import. After readdir lists entries, each entry is lstat'd; if the result is a symbolic link, the copy aborts. Local import policy rejects symlinks entirely because cross-platform symlink semantics differ and following links can escape the dropped subtree.","triggerScenarios":"Importing a local directory that contains a symlink. The lstat on a child entry returns isSymbolicLink() true, triggering the rejection before any copy attempt.","commonSituations":"Importing a project directory containing node_modules symlinks (pnpm, yarn workspaces). Importing a directory with config symlinks (e.g., .bashrc -> dotfiles/repo). macOS app bundles that use symlinks internally. Imported folder from a Linux environment where symlinks are common.","solutions":["Remove or resolve symlinks in the source directory before importing.","Use `find /source -type l` to identify all symlinks, then decide which to remove or dereference.","If pnpm/yarn symlinks are the cause, run `pnpm install` or `yarn install` on the destination after importing the non-symlink files."],"exampleFix":"// before: import /project containing symlink node_modules/.pnpm\n// after: dereference or remove symlinks first\n//   find /project -type l -delete   # remove symlinks\n//   or: cp -rL /project /resolved-project  # dereference, then import /resolved-project","handlingStrategy":"validation","validationCode":"const { readdir, lstat } = await import('node:fs/promises')\nconst { join } = await import('node:path')\n\nasync function findSymlinks(dir: string): Promise<string[]> {\n  const links: string[] = []\n  async function visit(d: string): Promise<void> {\n    for (const entry of await readdir(d, { withFileTypes: true })) {\n      const p = join(d, entry.name)\n      const st = await lstat(p)\n      if (st.isSymbolicLink()) links.push(p)\n      else if (st.isDirectory()) await visit(p)\n    }\n  }\n  await visit(dir)\n  return links\n}\n// const links = await findSymlinks(sourceDir)\n// if (links.length) throw new Error(`Remove symlinks first: ${links.join(', ')}`)","typeGuard":null,"tryCatchPattern":"try {\n  await importLocalSource(sourcePath, destDir)\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith('Symlink not allowed')) {\n    showUserError(`${error.message} — remove or dereference the symlink and retry.`)\n    return\n  }\n  throw error\n}","preventionTips":["Scan source directories with `find <source> -type l` before importing.","Dereference symlinks with `cp -rL` if you need their content.","Re-run package manager install (pnpm/yarn) on the destination to recreate managed symlinks."],"tags":["symlink","filesystem","local-import","security","ipc"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}