{"record":{"id":"7ef0e36a7e031bcb","repo":"stablyai/orca","slug":"symlink-not-allowed-in-displaypath","errorCode":null,"errorMessage":"Symlink not allowed in '${displayPath}'","messagePattern":"Symlink not allowed in '(.+?)'","errorType":"exception","errorClass":"RuntimeUploadSymlinkError","httpStatus":null,"severity":"warning","filePath":"src/main/ipc/filesystem-mutations.ts","lineNumber":580,"sourceCode":"      })\n      totalBytes += stagedFile.byteLength\n      entries.push(stagedFile.entry)\n    }\n  }\n\n  await visit(rootPath)\n  return entries\n}\n\nasync function stageFileEntry(\n  filePath: string,\n  relativePath: string,\n  options?: { rootRealPath?: string; totalBytesBefore?: number }\n): Promise<{ entry: StagedExternalImportEntry; byteLength: number }> {\n  const statResult = await lstat(filePath)\n  const displayPath = normalizeRelativeUploadPath(relativePath)\n  if (statResult.isSymbolicLink()) {\n    throw new RuntimeUploadSymlinkError(`Symlink not allowed in '${displayPath}'`)\n  }\n  if (!statResult.isFile()) {\n    throw new Error(`Unsupported file type in '${displayPath}'`)\n  }\n  if (options?.rootRealPath) {\n    await assertRealPathInsideRoot(options.rootRealPath, filePath, displayPath)\n  }\n  const initialTotalBytes =\n    options?.totalBytesBefore === undefined\n      ? statResult.size\n      : options.totalBytesBefore + statResult.size\n  assertRemoteUploadBudget(relativePath, statResult.size, initialTotalBytes)\n  const fileHandle = await open(filePath, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0))\n  try {\n    const openedStat = await fileHandle.stat()\n    if (!openedStat.isFile()) {\n      throw new Error(`Unsupported file type in '${displayPath}'`)\n    }","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/filesystem-mutations.ts#L562-L598","documentation":"Thrown as RuntimeUploadSymlinkError by stageFileEntry() when a staged single file lstat()s as a symbolic link. stageFileEntry is used both for child files during directory staging and for a single-file source in stageOneSourceForRuntimeUpload. The dedicated error class is caught upstairs and converted to { status: 'skipped', reason: 'symlink' }, so a symlinked top-level file is skipped rather than having its target uploaded.","triggerScenarios":"A single-file source passed to runtime-upload staging lstat()s as a symlink (isSymbolicLink()), or a child file staged from a directory is a symlink; stageFileEntry rejects it before opening.","commonSituations":"User selected a symlinked file (a linked shortcut) for upload; a tree contains symlinked dotfiles or linked assets; tooling created symlinks to shared files that ended up in the selection.","solutions":["Select the real target file instead of the symlink, or copy the target content to a regular file and upload that.","Resolve symlinks in the selection UI before staging so only regular files are passed.","Treat the skipped result as expected and inform the user that symlinked files are not uploaded."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Detect a symlinked single-file source before staging\nimport { lstat } from 'node:fs/promises'\nasync function isSymlinkFile(p: string): Promise<boolean> {\n  try { return (await lstat(p)).isSymbolicLink() } catch { return false }\n}","typeGuard":null,"tryCatchPattern":"const res = await stageOneSourceForRuntimeUpload(src)\nif (res.status === 'skipped' && res.reason === 'symlink') {\n  // tell the user the selected file is a symlink; offer to upload its real target\n}","preventionTips":["Resolve symlinked selections to their real targets in the UI before staging.","Inform users that symlinked files are skipped, not followed, by runtime upload.","Replace linked assets with copies if their content must be uploaded."],"tags":["symlink","upload","runtime-upload","staging","skipped"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}