stablyai/orca · error · Error
File changed during import: '${basename(srcPath)}'
Error message
File changed during import: '${basename(srcPath)}' What it means
Thrown in copyLocalFileNoFollow after opening the source with O_NOFOLLOW. The post-open fstat (openedStat) is compared against the pre-open lstat (beforeOpenStat): size, inode, and device must all match. If any differ, the file was swapped between the lstat and the open. Streaming from the O_NOFOLLOW handle pins the authorized file identity, but this check ensures the handle actually refers to the file that was validated.
Source
Thrown at src/main/ipc/filesystem-mutations.ts:738
let destinationCreated = false
const sourceHandle = await open(srcPath, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0))
let destinationHandle: Awaited<ReturnType<typeof open>> | null = null
try {
const openedStat = await sourceHandle.stat()
if (
!openedStat.isFile() ||
(typeof beforeOpenStat.size === 'number' && openedStat.size !== beforeOpenStat.size) ||
(typeof beforeOpenStat.ino === 'number' &&
beforeOpenStat.ino !== 0 &&
openedStat.ino !== 0 &&
openedStat.ino !== beforeOpenStat.ino) ||
(typeof beforeOpenStat.dev === 'number' &&
beforeOpenStat.dev !== 0 &&
openedStat.dev !== 0 &&
openedStat.dev !== beforeOpenStat.dev)
) {
throw new Error(`File changed during import: '${basename(srcPath)}'`)
}
// Why: copyFile(path, path) would follow a source symlink if the source is
// swapped after validation. Streaming from an O_NOFOLLOW handle keeps the
// authorized file identity pinned for the copy.
destinationHandle = await open(dstPath, 'wx')
destinationCreated = true
await pipeline(sourceHandle.createReadStream(), destinationHandle.createWriteStream())
} catch (error) {
if (destinationCreated) {
await unlink(dstPath).catch(() => {})
}
throw error
} finally {
await sourceHandle.close().catch(() => {})
await destinationHandle?.close().catch(() => {})
}
}
View on GitHub (pinned to 1136503c6a)
Solutions
- Ensure the source file is not being modified during the import.
- Copy the file to a stable local path before importing.
- Retry the import after the source has stabilized.
Example fix
// before: import a file that a build tool is atomically replacing // after: snapshot the file first // cp /project/output.bin /tmp/stable.bin // import /tmp/stable.bin
Defensive patterns
Strategy: retry
Try / catch
try {
await importLocalSource(sourcePath, destDir)
} catch (error) {
if (error instanceof Error && error.message.includes('File changed during import')) {
showUserWarning('The source file changed during import. Ensure it is stable and retry.')
return
}
throw error
} Prevention
- Do not import files that are being rewritten by editors, builds, or atomic-rename daemons.
- Snapshot volatile files with `cp` before importing.
- Retry after the source has stabilized if the race is transient.
When it happens
Trigger: Between the beforeOpenStat lstat and the O_NOFOLLOW open, the source file is replaced, truncated, or moved such that its size, inode, or device number changes. The open succeeds but fstat reports a different identity.
Common situations: A file being rewritten by an editor or build tool during import. Atomic file replacement (write-to-temp-then-rename) happening between lstat and open. Importing from a network filesystem where inode/device mapping is not stable.
Related errors
- File changed during upload staging: '${displayPath}'
- Symlink not allowed in '${entry.name}'
- Symlink not allowed in '${basename(srcPath)}'
- Destination file appeared before download completed
- Path escaped upload root during staging: '${displayPath}'
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/48447994b7203973.
Report an issue: GitHub.