---
title: Project folder missing (recreate or relink)
---

# Project folder missing — recreate or relink

## What it is

When a session tries to start and its project's folder doesn't exist on disk, Omniscio now fails the spawn immediately with a clear, actionable banner instead of silently looping with the misleading error "spawn cmd.exe ENOENT". This happens when the folder was moved, renamed, deleted, or lives on a drive that isn't currently mounted (removed USB stick, unmounted network share, unplugged external drive).

You'll see the session flip to red Error status and a red banner slides in above the message composer with:

- The heading **"Project folder is missing"**
- The exact path Omniscio expected (e.g. `E:/Projects/MyThing`)
- A short note that the folder may have been moved, renamed, or is on an unmounted drive
- A **"Recreate Folder"** button on the right

The chat itself also has a one-line system message naming the missing path and pointing at the banner.

## Where to find it

The banner appears inside the **session panel**, directly above the message composer — you don't have to go looking for it. The session's row in the sidebar simultaneously flips to a red Error status. The same event also drops a one-line system message into the conversation itself, naming the missing path and pointing up at the banner.

## How it behaves

### A removed worktree falls back — it does not alarm

Worktree-isolated sessions run inside a temporary worktree checkout, not the project folder itself. If that worktree is later removed (e.g. a background cleanup reaps a finished one), the session's saved working directory points at nothing — but the **project folder is still fine**. Omniscio does NOT raise the "folder is missing" banner in that case: the pre-spawn check re-resolves the working directory and falls back to the project folder (the same fallback `resolveSessionWorkDir` already uses everywhere else), so the session simply spawns there. The banner is reserved for when the **project folder itself** is genuinely gone. This is why a reaped worktree no longer mislabels your project/Hub folder as missing, and no longer loops the session in a retry storm.

When the banner DOES fire, it shows the **actual** missing directory carried by the event — never a hard-coded project root — so the path you see is always the real one.

### What to do about it

**Option 1 — Recreate the folder in place.** Click **Recreate Folder**. Omniscio creates the folder at exactly the path the project stores, then automatically restarts the session. The banner disappears and the session returns to normal. Use this when the folder was accidentally deleted or when you're happy to start it fresh at the original path.

**Option 2 — The drive is unmounted.** Plug in the external drive / reconnect the network share, then click **Recreate Folder**. If the folder already exists on the re-mounted drive, Omniscio skips the create and just restarts — you get your existing files back untouched.

**Option 3 — The folder moved and you want to keep the content.** Don't click the recreate button. Instead, close the banner by moving the real folder back to the path the project expects (shown in the banner), or edit the project to point at the new path via the project's three-dot menu → Edit → change the folder path. Re-launch the session from the sidebar.

While the IPC call is in flight the button reads **"Recreating…"** and is disabled. If the create fails — permission denied, invalid drive letter, read-only volume — the banner shows the specific error inline in a red pill so you can react.

### Automatic recovery waits for the folder

Omniscio's self-healing features cooperate with this state instead of fighting it. When [crash recovery](crash-recovery.md), [aborted-response recovery](aborted-response-recovery.md), or the background safety net that re-drives failed sessions reaches a session whose folder is missing, it checks the folder first and simply waits — nothing is charged against any retry limit (no daily-cap attempts, no quarantine strikes, no backoff climb), because no retry can succeed until the folder is back. The first blocked attempt raises the same red banner plus a one-line note in the chat, so you know why the session is holding. The moment the folder exists again — drive plugged back in, folder restored or recreated — recovery resumes on its own. No manual retry needed.

### Why it fails fast now (vs. the old silent loop)

Node's `child_process.spawn()` reports a missing working-directory (`cwd`) as `"spawn cmd.exe ENOENT"` — which looks identical to "couldn't find the cmd.exe binary" and doesn't mention that the cwd is the actual problem. Before this change the spawn would just fail with that cryptic message, Omniscio would retry, and the session would stay stuck without the user understanding why. The real cause was the libuv `UV_ENOENT` / `-4058` error bubbling up from the kernel on a non-existent directory.

The fix: Omniscio pre-checks `existsSync(workingDir)` immediately before spawn. If the directory is missing, Omniscio writes a system message naming the path, emits a push event that the UI reacts to with the red banner, and marks the session status as `error` — all without ever calling `spawn()`. SSH sessions are exempt from this check because the working directory lives on the remote host, not the local filesystem.

## For agents

1. In [src/main/process/spawn-cluster-manager.ts](/src/main/process/spawn-cluster-manager.ts), `spawnLocalStreamJson`'s pre-spawn gate (`resolveWorkdirBootstrap`) calls `existsSync(session.workingDir)` right before the `spawn()`. If the directory is missing it re-resolves via `resolveSessionWorkDir` + `decideSpawnWorkDir`: a removed worktree whose fallback (the project folder) exists is re-pointed and the spawn proceeds; only a genuinely-missing resolved dir emits a system message, fires `emitPush(IPC.PROJECT_FOLDER_MISSING, { projectId, path })` with the **accurate resolved path**, and marks the session `error` — then returns without spawning. (This is the spawn side of the backend-spawn contract's §1 "cwd comes from resolveSessionWorkDir" invariant.)
2. The renderer's [src/renderer/src/hooks/useProjectPushSync.ts](/src/renderer/src/hooks/useProjectPushSync.ts) listens for `PROJECT_FOLDER_MISSING`, adds the `projectId` to the Zustand `missingFolderProjectIds: Set<string>` slice, and records the pushed `path` in the parallel `missingFolderPaths: Map<string,string>` ([session-project-folder-slice.ts](/src/renderer/src/stores/slices/session-project-folder-slice.ts)). This is transient renderer state — not persisted to SQLite — and clears on the next successful recreate or account switch.
3. [src/renderer/src/features/sessions/ProjectFolderMissingBanner.tsx](/src/renderer/src/features/sessions/ProjectFolderMissingBanner.tsx) mounts above the composer in every SessionPanel and renders only when the active session's `projectId` is in that Set. It displays the real missing path from `missingFolderPaths`, falling back to the project's configured path. It's a pure read of renderer state — a stale session panel won't show the banner for another project's missing folder.
4. The **Recreate Folder** button invokes `PROJECT_RECREATE_FOLDER` IPC ([src/main/ipc/project-handlers.ts](/src/main/ipc/project-handlers.ts)). The handler looks up the project, runs `resolveProjectWorkDir()` to expand any `__claude__` sentinel to the real `~/Claude` path, calls `mkdirSync(path, { recursive: true })`, emits `PROJECTS_CHANGED`, and returns `{ path, created }`. If the folder already exists it returns `created: false` without touching the filesystem.
5. On success, the banner calls `restartSession(sessionId)` so the session retries the spawn — this time the `existsSync` check passes and `spawn()` runs normally.

The project record itself is never modified — `folderPath` stays at whatever you originally configured. That's intentional: the recreate button is about restoring the folder at the expected path, not re-pointing the project.

## Related

A session that is holding rather than failing usually has one of the other "waiting on you" causes, and [session-stuck-in-needs-you.md](session-stuck-in-needs-you.md) walks through all seven. The recovery machinery that deliberately stands down while the folder is gone is described in [crash-recovery.md](crash-recovery.md) and [aborted-response-recovery.md](aborted-response-recovery.md), and it is worth reading if you want to understand why nothing is retrying. When you need to dig into what Omniscio did at spawn time, [logs-and-debugging.md](logs-and-debugging.md) says where those errors land. If you would rather move the project to the folder than the folder to the project, [edit-a-project.md](edit-a-project.md) covers changing a project's stored path.
