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

  1. 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
  2. Pick a directory under the user's home or another user-writable location
  3. Create the directory manually in a terminal to confirm the account can, then set it in the app
  4. 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

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.