stablyai/orca · warning · RuntimeUploadSymlinkError
Symlink not allowed in '${normalizeRelativeUploadPath(relati
Error message
Symlink not allowed in '${normalizeRelativeUploadPath(relative(rootPath, dirPath))}' What it means
Thrown as RuntimeUploadSymlinkError by stageDirectoryEntries() when a visited directory path itself lstat()s as a symbolic link. stageDirectoryEntries is part of the runtime-upload staging path (reading files to base64 for remote/agent upload); symlinks are forbidden to prevent traversal and non-portable link semantics. The dedicated error class is caught one frame up in stageOneSourceForRuntimeUpload and converted into a { status: 'skipped', reason: 'symlink' } result, so the whole source is skipped rather than failing the batch.
Source
Thrown at src/main/ipc/filesystem-mutations.ts:530
return { sourcePath, status: 'skipped', reason: 'symlink' }
}
return {
sourcePath,
status: 'failed',
reason: error instanceof Error ? error.message : String(error)
}
}
}
async function stageDirectoryEntries(rootPath: string): Promise<StagedExternalImportEntry[]> {
const entries: StagedExternalImportEntry[] = [{ relativePath: '', kind: 'directory' }]
let totalBytes = 0
const rootRealPath = await realpath(rootPath)
async function visit(dirPath: string): Promise<void> {
const dirStat = await lstat(dirPath)
if (dirStat.isSymbolicLink()) {
throw new RuntimeUploadSymlinkError(
`Symlink not allowed in '${normalizeRelativeUploadPath(relative(rootPath, dirPath))}'`
)
}
if (!dirStat.isDirectory()) {
throw new Error(
`Unsupported file type in '${normalizeRelativeUploadPath(relative(rootPath, dirPath))}'`
)
}
await assertRealPathInsideRoot(
rootRealPath,
dirPath,
normalizeRelativeUploadPath(relative(rootPath, dirPath))
)
const dirEntries = await readdir(dirPath, { withFileTypes: true })
for (const entry of dirEntries) {
const childPath = join(dirPath, entry.name)
const childRelativePath = normalizeRelativeUploadPath(relative(rootPath, childPath))
if (entry.isSymbolicLink()) {View on GitHub (pinned to 1136503c6a)
Solutions
- Expect the source to be reported as skipped; copy the real content into a non-symlinked directory and upload that.
- Remove or un-symlink the offending directory in the source tree before staging.
- Filter symlinked directories out of the upload selection in the UI.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-detect symlinked directories before runtime-upload staging
import { lstat } from 'node:fs/promises'
async function isSymlinkDir(p: string): Promise<boolean> {
try { return (await lstat(p)).isSymbolicLink() } catch { return false }
} Try / catch
// stageOneSourceForRuntimeUpload already maps RuntimeUploadSymlinkError -> skipped;
// callers should branch on the result status:
const res = await stageOneSourceForRuntimeUpload(src)
if (res.status === 'skipped' && res.reason === 'symlink') {
// report to user; offer to upload the real target instead
} Prevention
- Filter symlinked directories out of the upload selection in the UI.
- Resolve symlinks to their real targets before staging if the content is needed.
- Treat skipped/symlink results as expected, not as crashes.
When it happens
Trigger: stageOneSourceForRuntimeUpload processes a directory source whose root or a visited subdirectory is a symlink; lstat reports the visited dirPath as isSymbolicLink() and RuntimeUploadSymlinkError is thrown.
Common situations: A dropped/uploaded directory tree that contains symlinked subfolders (common in monorepos, build output dirs, or linked packages); the user selected a top-level path that is itself a symlink to a directory.
Related errors
- Symlink not allowed in '${childRelativePath}'
- Symlink not allowed in '${displayPath}'
- Unsupported file type in '${normalizeRelativeUploadPath(rela
- Unsupported file type in '${childRelativePath}'
- Unsupported file type in '${displayPath}'
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/9c6b6ae1ddcbcae6.
Report an issue: GitHub.