multica-ai/multica · error
migrate task-local hermes memory %s into %s: %w
Error message
migrate task-local hermes memory %s into %s: %w
What it means
Returned by migrateHermesTaskMemories when copyHermesMemoryEntry fails while copying one entry (file or subdir) from the task-local memories dir into the staging dir. Because migration must be all-or-nothing (source is deleted only after a full copy), any single-entry failure aborts the whole migration and the mount.
Source
Thrown at server/internal/daemon/execenv/hermes_memory.go:237
entries, err := os.ReadDir(taskDir)
if err != nil {
return fmt.Errorf("read task-local hermes memories %s: %w", taskDir, err)
}
if len(entries) == 0 {
return nil
}
staging, err := newHermesStoreStaging(storeDir)
if err != nil {
return err
}
defer os.RemoveAll(staging) // no-op once the staging dir has been promoted
for _, entry := range entries {
src := filepath.Join(taskDir, entry.Name())
if err := copyHermesMemoryEntry(src, filepath.Join(staging, entry.Name()), entry); err != nil {
return fmt.Errorf("migrate task-local hermes memory %s into %s: %w", src, storeDir, err)
}
}
promoted, err := promoteHermesStoreStaging(staging, storeDir, hermesStorePopulated)
if err != nil {
return err
}
if !promoted {
logger.Info("execenv: another task populated the hermes memory store first; keeping it", "store", storeDir)
return nil
}
logger.Info("execenv: migrated task-local hermes memories into agent store", "store", storeDir, "entries", len(entries))
return nil
}
// newHermesStoreStaging creates the scratch directory a store migration copies
// into. It is a sibling of the store so the promoting rename stays within one
// filesystem, and dot-prefixed so it is obvious it is not a store of its own.View on GitHub (pinned to 2c0912b6ec)
Solutions
- Freeze/clean the volume holding the profile dir (staging is a sibling of the store) and retry the task.
- Inspect the named src entry from the error message: fix its permissions or remove it if it is junk (broken symlink, socket) that Hermes never needed.
- Ensure the daemon user can read every file under the task-local memories dir.
Defensive patterns
Strategy: retry
Validate before calling
// Free-space sanity check before a migration copies bytes:
var st syscall.Statfs_t
if err := syscall.Statfs(filepath.Dir(storeDir), &st); err == nil && st.Bavail*uint64(st.Bsize) < needBytes {
return errors.New("insufficient space for memory migration")
} Try / catch
if err := migrateHermesTaskMemories(src, store, logger); err != nil {
if isTransientCopyErr(err) { // ENOSPC resolved, EACCES fixed
err = migrateHermesTaskMemories(src, store, logger) // source untouched on failure, retry is safe
}
} Prevention
- Keep headroom on the profile-dir volume before daemon upgrades
- All-or-nothing staging means a failed copy leaves the source intact — fix the cause, then retry
- Remove junk entries (sockets, dead symlinks) from task memories dirs
When it happens
Trigger: copyHermesMemoryEntry fails: source file unreadable (EACCES), disk full while copying into staging, an entry whose type changed between ReadDir and copy (symlink/dir race), or an irregular file type the copier rejects.
Common situations: Upgrading a daemon on a nearly-full disk; a memories tree containing odd entries (sockets, broken symlinks) written by a crashed task; permission mismatch between overlay owner and daemon user.
Related errors
- create hermes memory staging dir in %s: %w
- create temp for %s: %w
- write temp for %s: %w
- remove stale memories path %s: %w
- read hermes memory store %s: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/6837a9cce37fd6a4.
Report an issue: GitHub.