NousResearch/hermes-agent · warning · Error

Parent directory does not exist

Error message

Parent directory does not exist

What it means

writeText never creates directory trees — by design it only writes a file whose parent directory already exists. After resolving the path through resolveRequestedPathForIpc (allowed-roots check), it verifies directoryExists(dirname(resolved)) and throws this error if the parent is missing. The companion error to 'Invalid path' and 'Content too large', it prevents the IPC from being used to materialize arbitrary directory structures.

Source

Thrown at apps/desktop/electron/main.ts:11805

// this never creates directory trees or escapes the allowed roots, and content
// is size-capped so it can't be abused as a bulk-write primitive.
ipcMain.handle('hermes:fs:writeText', async (_event, filePath, content) => {
  const raw = String(filePath || '').trim()

  if (!raw) {
    throw new Error('Invalid path')
  }

  const text = String(content ?? '')

  if (text.length > 1_000_000) {
    throw new Error('Content too large')
  }

  const resolved = resolveRequestedPathForIpc(expandUserPath(raw), { purpose: 'Write text file' })

  if (!directoryExists(path.dirname(resolved))) {
    throw new Error('Parent directory does not exist')
  }

  await fs.promises.writeFile(resolved, text, 'utf8')

  return { path: resolved }
})

// Move a file/folder to the OS trash (recoverable) — the VS Code "Delete"
// default. `shell.trashItem` routes to Finder/Explorer/Files trash per platform.
ipcMain.handle('hermes:fs:trash', async (_event, targetPath) => {
  const target = String(targetPath || '').trim()

  if (!target) {
    throw new Error('Invalid delete')
  }

  await shell.trashItem(target)

View on GitHub (pinned to c896c09c42)

Solutions

  1. Create the parent directory first (via the project-creation flow or hermes:setting:defaultProjectDir:set which mkdirs), then retry the write
  2. Verify the captured project path still exists before writing — re-resolve it if the project was moved
  3. Do not rely on writeText to bootstrap a directory tree; it intentionally refuses

Example fix

// before
await ipc.invoke('hermes:fs:writeText', `${projectDir}/notes/IDEA.md`, text)

// after
await ipc.invoke('hermes:setting:defaultProjectDir:set', `${projectDir}/notes`) // or otherwise mkdir
await ipc.invoke('hermes:fs:writeText', `${projectDir}/notes/IDEA.md`, text)
Defensive patterns

Strategy: validation

Validate before calling

const parent = path.dirname(filePath)
if (!existsSync(parent)) { await ensureDirectory(parent) // via a mkdir-capable flow
}
await ipc.invoke('hermes:fs:writeText', filePath, content)

Type guard

function parentDirExists(p: string): boolean { return existsSync(path.dirname(p)) }

Try / catch

catch (e) { if (e instanceof Error && e.message === 'Parent directory does not exist') { await createParentThenRetry() } else throw e }

Prevention

When it happens

Trigger: Writing to a path whose parent directory has not been created yet — e.g. <project>/.hermes/notes.md before .hermes/ exists, or a project directory that was trashed/renamed since the UI captured the path.

Common situations: Project folder deleted or moved after the settings UI captured the default project dir; a fresh checkout where an expected subdirectory is gitignored or absent; race between project creation and the first writeText.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/bc3539286b36c937. Report an issue: GitHub.