multica-ai/multica · error
read overlay home: %w
Error message
read overlay home: %w
What it means
reconcileMirroredEntries could not list the task-local overlay home (os.ReadDir(hermesHome)) while pruning entries that are no longer mirrored from the shared home. The overlay directory itself is unreadable or was removed out from under the prepare step. The reconciliation exists so deleted-in-shared-home entries and Windows copy-fallback leftovers do not survive as stale state.
Source
Thrown at server/internal/daemon/execenv/hermes_home.go:551
continue
}
src := filepath.Join(sharedHome, name)
dst := filepath.Join(hermesHome, name)
if err := linkSharedHermesEntry(src, dst); err != nil {
return fmt.Errorf("mirror %s: %w", name, err)
}
mirrored[name] = struct{}{}
}
return reconcileMirroredEntries(hermesHome, mirrored)
}
// reconcileMirroredEntries removes overlay entries that are neither overlay-owned
// nor currently mirrored from the shared home, so a shared entry deleted between
// runs (or a Windows copy-fallback left behind) doesn't survive as stale state.
func reconcileMirroredEntries(hermesHome string, mirrored map[string]struct{}) error {
entries, err := os.ReadDir(hermesHome)
if err != nil {
return fmt.Errorf("read overlay home: %w", err)
}
for _, entry := range entries {
name := entry.Name()
if isHermesOverlayOwnedEntry(name) {
continue
}
if _, keep := mirrored[name]; keep {
continue
}
if err := os.RemoveAll(filepath.Join(hermesHome, name)); err != nil {
return fmt.Errorf("reconcile stale %s: %w", name, err)
}
}
return nil
}
// prepareHermesTaskLocalState migrates an overlay built by an older daemon away
// from the shared Hermes SQLite session store. Without the marker, state.db andView on GitHub (pinned to 2c0912b6ec)
Solutions
- Check the overlay dir exists and is readable by the daemon user: `ls -la <envRoot>/hermes-home`.
- Delete the whole overlay dir and let the next prepare rebuild it from the shared home.
- Serialize env GC/teardown against task start so the overlay is not deleted mid-prepare.
- Check dmesp/logs for underlying I/O errors (read-only remount, disk failure) and remount/replace the volume.
Defensive patterns
Strategy: validation
Validate before calling
if fi, err := os.Stat(hermesHome); err != nil {
return fmt.Errorf("overlay home missing before reconcile: %w", err)
} else if !fi.IsDir() || fi.Mode().Perm()&0o400 == 0 {
return fmt.Errorf("overlay home not a readable dir: %s", hermesHome)
} Try / catch
if err := reconcileMirroredEntries(hermesHome, mirrored); err != nil {
if errors.Is(err, fs.ErrNotExist) {
// overlay vanished (GC race): recreate from scratch instead of failing
return mirrorSharedHermesHome(sharedHome, hermesHome, logger)
}
return err
} Prevention
- Serialize env GC/teardown with task start (lock per env RootDir).
- Treat the overlay dir as disposable: on odd failures, delete and rebuild it.
- Monitor for read-only filesystems under the env root.
When it happens
Trigger: The generated overlay dir (env RootDir/hermes-home) has mode 000, was deleted concurrently (env teardown/GC racing a task start), or sits on a failing filesystem.
Common situations: Cloud GC loop wiping env dirs at the same moment a task starts; a previous crash left a partially-created overlay with wrong permissions; disk-full filesystem going read-only.
Related errors
- mint PAT: target API URL not set
- mint PAT: response missing token
- daemon profile is not resolved yet; token sync skipped
- API error: ${res.status} ${res.statusText}
- Upload failed: ${res.status}
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/1cbec38391355caa.
Report an issue: GitHub.