stablyai/orca · error · Error
Cannot write to a directory
Error message
Cannot write to a directory
What it means
Thrown by the local-write branch of a writeFile IPC handler (src/main/ipc/filesystem.ts:867). After resolveAuthorizedPath returns a path, the handler lstats it; if it is a directory, writing file content is rejected. ENOENT is allowed (creating a new file) and other stat errors are rethrown.
Source
Thrown at src/main/ipc/filesystem.ts:867
_event,
args: { filePath: string; content: string; connectionId?: string } & SshMutationExpectation
): Promise<void> => {
assertSshMutationExpectation(
args.connectionId,
args.expectedSshTargetId,
args.expectedSshConnectionGeneration,
args.expectedExecutionHostId
)
if (args.connectionId) {
const provider = requireSshFilesystemProvider(args.connectionId)
return provider.writeFile(args.filePath, args.content)
}
const filePath = await resolveAuthorizedPath(args.filePath, store)
try {
const fileStats = await lstat(filePath)
if (fileStats.isDirectory()) {
throw new Error('Cannot write to a directory')
}
} catch (error) {
if (!isENOENT(error)) {
throw error
}
}
await writeFile(filePath, args.content, 'utf-8')
}
)
ipcMain.handle(
'fs:deletePath',
async (
_event,
args: {
targetPath: string
connectionId?: stringView on GitHub (pinned to 1136503c6a)
Solutions
- Append an actual file name to the directory path before writing.
- Strip trailing slashes from filePath before invoking the handler.
- If writing inside the directory is intended, use path.join(dirPath, fileName).
Example fix
// before: target resolves to a directory
await invoke('fs:writeFile', { filePath: '/repo/src', content })
// after: target is a file inside the directory
await invoke('fs:writeFile', { filePath: '/repo/src/notes.md', content }) Defensive patterns
Strategy: validation
Validate before calling
import { lstat } from 'node:fs/promises'
async function assertIsFilePath(p: string): Promise<void> {
const s = await lstat(p).catch(() => null)
if (s?.isDirectory()) throw new Error(`Refusing to write: ${p} is a directory`)
} Prevention
- Normalize filePath to strip trailing slashes before writing.
- When the user picks a destination, reject directory entries.
- Join directory + filename explicitly rather than writing to the bare folder path.
When it happens
Trigger: Calling the write handler with a filePath that resolves to an existing directory: a trailing slash, a bare folder path like '/repo/src', or a path where a directory of the same name already exists.
Common situations: Path normalization bug appending '/' or joining incorrectly; a 'save file' flow that accepted a directory picker result; resolveAuthorizedPath resolving a symlinked folder; user typing a folder name in a save dialog.
Related errors
- No Claude credentials found in ${resolvedDir}. Run `claude l
- --serve-project-root must be a directory: ${options.projectR
- Selected file is not a markdown document.
- Upload source changed while being inspected: ${sourcePath}
- Cannot download to a directory
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/25ca11a6cbcf46d2.
Report an issue: GitHub.