multica-ai/multica · error
stat codex home %s: %w
Error message
stat codex home %s: %w
What it means
verifyCodexHomeRoot stats the codexHome path with os.Lstat to compare against the opened handle. Failure means the path cannot be stat'ed at all: it vanished between os.OpenRoot and the Lstat, or a parent directory became unreadable.
Source
Thrown at server/internal/daemon/execenv/codex_home.go:988
if err := verifyCodexHomeRoot(root, codexHome, key); err != nil {
root.Close()
return nil, err
}
return root, nil
}
// verifyCodexHomeRoot proves that root is the directory codexHome names right
// now: not reached through a symlink, and the same directory os.Lstat sees at
// that path. It is separate from openVerifiedCodexHomeRoot so the swap case can
// be tested deterministically instead of by racing.
func verifyCodexHomeRoot(root *os.Root, codexHome, key string) error {
opened, err := root.Stat(".")
if err != nil {
return fmt.Errorf("stat opened codex home %s: %w", codexHome, err)
}
current, err := os.Lstat(codexHome)
if err != nil {
return fmt.Errorf("stat codex home %s: %w", codexHome, err)
}
if current.Mode()&os.ModeSymlink != 0 {
return fmt.Errorf("codex home %s is a symlink; refusing to write %s through it", codexHome, key)
}
if !os.SameFile(opened, current) {
return fmt.Errorf("codex home %s was replaced while opening it; refusing to write %s through it", codexHome, key)
}
return nil
}
// materialiseInCodexHome writes src to relPath inside codexHome using
// root-scoped operations, so no symlink below the task home can redirect the
// daemon's mkdir, remove, or write outside it.
//
// This matters because a task home is reused: a prepare can run against a
// directory a previous task already wrote to. Without the root, a task that
// replaced an intermediate directory of its own home with a link to somewhere
// else would have the daemon delete and overwrite the link target on the nextView on GitHub (pinned to 2c0912b6ec)
Solutions
- Serialize workspace cleanup with task start (don't delete a home while a prepare is in flight)
- Retry prepare after the race window passes
- Ensure parent directories of the home stay searchable by the daemon user
Defensive patterns
Strategy: retry
Try / catch
if err := prepareCodexHome(...); err != nil {
if errors.Is(err, fs.ErrNotExist) && strings.Contains(err.Error(), "stat codex home") {
// home vanished mid-open: recreate and retry once
_ = os.MkdirAll(codexHome, 0o755)
err = prepareCodexHome(...)
}
} Prevention
- Never run workspace reapers concurrently with task start
- Log which process removes task homes when this fires
When it happens
Trigger: The task home directory is removed concurrently right after being opened; a parent of the path is chmod'ed to deny search; the mount disappears.
Common situations: Workspace reaper or cleanup job racing task start; a task deleting its own home in a previous run's teardown.
Related errors
- create %s copy %s: %w
- read attachment %s: %w
- open codex home %s: %w
- stat opened codex home %s: %w
- codex home %s was replaced while opening it; refusing to wri
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/c7809e3d7bc458f1.
Report an issue: GitHub.