{"record":{"id":"6837a9cce37fd6a4","repo":"multica-ai/multica","slug":"migrate-task-local-hermes-memory-s-into-s-w","errorCode":null,"errorMessage":"migrate task-local hermes memory %s into %s: %w","messagePattern":"migrate task-local hermes memory (.+?) into (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/daemon/execenv/hermes_memory.go","lineNumber":237,"sourceCode":"\n\tentries, err := os.ReadDir(taskDir)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read task-local hermes memories %s: %w\", taskDir, err)\n\t}\n\tif len(entries) == 0 {\n\t\treturn nil\n\t}\n\n\tstaging, err := newHermesStoreStaging(storeDir)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer os.RemoveAll(staging) // no-op once the staging dir has been promoted\n\n\tfor _, entry := range entries {\n\t\tsrc := filepath.Join(taskDir, entry.Name())\n\t\tif err := copyHermesMemoryEntry(src, filepath.Join(staging, entry.Name()), entry); err != nil {\n\t\t\treturn fmt.Errorf(\"migrate task-local hermes memory %s into %s: %w\", src, storeDir, err)\n\t\t}\n\t}\n\n\tpromoted, err := promoteHermesStoreStaging(staging, storeDir, hermesStorePopulated)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !promoted {\n\t\tlogger.Info(\"execenv: another task populated the hermes memory store first; keeping it\", \"store\", storeDir)\n\t\treturn nil\n\t}\n\tlogger.Info(\"execenv: migrated task-local hermes memories into agent store\", \"store\", storeDir, \"entries\", len(entries))\n\treturn nil\n}\n\n// newHermesStoreStaging creates the scratch directory a store migration copies\n// into. It is a sibling of the store so the promoting rename stays within one\n// filesystem, and dot-prefixed so it is obvious it is not a store of its own.","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/daemon/execenv/hermes_memory.go#L219-L255","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Free-space sanity check before a migration copies bytes:\nvar st syscall.Statfs_t\nif err := syscall.Statfs(filepath.Dir(storeDir), &st); err == nil && st.Bavail*uint64(st.Bsize) < needBytes {\n    return errors.New(\"insufficient space for memory migration\")\n}","typeGuard":null,"tryCatchPattern":"if err := migrateHermesTaskMemories(src, store, logger); err != nil {\n    if isTransientCopyErr(err) { // ENOSPC resolved, EACCES fixed\n        err = migrateHermesTaskMemories(src, store, logger) // source untouched on failure, retry is safe\n    }\n}","preventionTips":["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"],"tags":["filesystem","hermes","migration","copy","disk-full"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}