NousResearch/hermes-agent · error · Error
Could not create directory: ${error.message}
Error message
Could not create directory: ${error.message} What it means
The 'hermes:setting:defaultProjectDir:set' IPC creates the chosen default project directory with fs.mkdirSync(next, {recursive:true}) before persisting it. If the OS refuses — EACCES, EPERM, ENAMETOOLONG, an existing file at that path, or an invalid path on the platform — the raw mkdir error is wrapped in this message. It is an environment/permissions error, not an app-logic error.
Source
Thrown at apps/desktop/electron/main.ts:11433
// settings mount and seeds the value into the picker; writing back persists
// it via writeDefaultProjectDir so resolveHermesCwd picks it up on the next
// session spawn (no app restart needed).
ipcMain.handle('hermes:setting:defaultProjectDir:get', async () => ({
dir: readDefaultProjectDir(),
defaultLabel: app.getPath('home'),
resolvedCwd: resolveHermesCwd()
}))
ipcMain.handle('hermes:workspace:sanitize', async (_event, cwd) => sanitizeWorkspaceCwd(cwd))
ipcMain.handle('hermes:setting:defaultProjectDir:set', async (_event, dir) => {
const next = typeof dir === 'string' && dir.trim() ? dir.trim() : null
if (next) {
try {
fs.mkdirSync(next, { recursive: true })
} catch (error) {
throw new Error(`Could not create directory: ${error.message}`)
}
}
writeDefaultProjectDir(next)
return { dir: next }
})
ipcMain.handle('hermes:setting:defaultProjectDir:pick', async () => {
const result = await dialog.showOpenDialog({
title: 'Choose default project directory',
properties: ['openDirectory', 'createDirectory'],
defaultPath: readDefaultProjectDir() || app.getPath('home')
})
if (result.canceled || result.filePaths.length === 0) {
return { canceled: true, dir: null }
}View on GitHub (pinned to c896c09c42)
Solutions
- Read error.message inside — EACCES/EPERM means permissions, EEXIST-with-file means a file blocks the dir, ENOENT on a parent usually means a typo
- Pick a directory under the user's home or another user-writable location
- Create the directory manually in a terminal to confirm the account can, then set it in the app
- On Windows avoid reserved names (CON, PRN) and over-long paths; on network drives ensure the mount is live
Example fix
# before: default project dir = /srv/projects (root-owned) # after sudo mkdir -p /srv/projects && sudo chown $USER /srv/projects # or pick ~/projects
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check writability before persisting
import { accessSync, constants } from 'fs'
accessSync(path.dirname(next), constants.W_OK) // throws early with a clearer signal
await ipc.invoke('hermes:setting:defaultProjectDir:set', next) Try / catch
try { await ipc.invoke('hermes:setting:defaultProjectDir:set', dir) } catch (e) { if (e instanceof Error && e.message.startsWith('Could not create directory:')) notify(`Pick a writable directory (${e.message})`) else throw e } Prevention
- Default the picker to a user-writable location (home dir)
- Test-create the directory in the picker flow before saving
- Avoid system-owned and disconnected network paths as project dirs
When it happens
Trigger: Setting a default project dir pointing to a read-only location, a path owned by another user, a path where a regular file already exists where a directory is expected, or a path with characters invalid on the host OS (e.g. reserved Windows names).
Common situations: Choosing a system directory (/proc, C:\Windows) or a network mount that is disconnected; running with restricted permissions; pasting a path that includes a filename where the directory should be.
Related errors
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/56fd12ddc3c85d27.
Report an issue: GitHub.