{"record":{"id":"2e95f90dae44cc87","repo":"multica-ai/multica","slug":"create-hermes-memory-store-s-w","errorCode":null,"errorMessage":"create hermes memory store %s: %w","messagePattern":"create hermes memory store (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/daemon/execenv/hermes_memory.go","lineNumber":154,"sourceCode":"}\n\n// mountHermesMemories points the overlay's memories/ at storeDir, so the agent's\n// memory outlives the task. Idempotent across Reuse: a link already pointing at\n// the store is left alone.\n//\n// A real memories/ directory left by an older daemon (or by a task that ran\n// without a store to key on) is migrated into the store rather than discarded —\n// but only into an empty store, so an upgrade never overwrites memory the agent\n// has already accumulated. A migration that cannot complete fails the overlay\n// rather than dropping the directory it could not carry over.\nfunc mountHermesMemories(hermesHome, storeDir string, logger *slog.Logger) error {\n\tdst := filepath.Join(hermesHome, hermesMemoriesEntry)\n\n\tif fi, err := os.Lstat(dst); err == nil {\n\t\tif fi.Mode()&os.ModeSymlink != 0 {\n\t\t\tif target, rlErr := os.Readlink(dst); rlErr == nil && filepath.Clean(target) == filepath.Clean(storeDir) {\n\t\t\t\tif err := os.MkdirAll(storeDir, 0o700); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"create hermes memory store %s: %w\", storeDir, err)\n\t\t\t\t}\n\t\t\t\ttouchHermesMemoryStore(storeDir, logger)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t} else if fi.IsDir() {\n\t\t\t// Runs before the store dir is created, so migration can publish a\n\t\t\t// fully-copied tree with one atomic rename. Fails closed: the source\n\t\t\t// dir below is only removed once every entry is safely in the store.\n\t\t\tif err := migrateHermesTaskMemories(dst, storeDir, logger); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\tif err := os.RemoveAll(dst); err != nil {\n\t\t\treturn fmt.Errorf(\"remove stale memories path %s: %w\", dst, err)\n\t\t}\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"stat memories path %s: %w\", dst, err)\n\t}","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/daemon/execenv/hermes_memory.go#L136-L172","documentation":"mountHermesMemories found the overlay's memories/ already symlinked to the intended store directory, but os.MkdirAll(storeDir, 0700) failed while ensuring the store exists. The per-agent memory store lives outside the task overlay so memory outlives tasks; the daemon both validates the link target and materializes the store in one idempotent step.","triggerScenarios":"The store path's parent (Multica profile dir) is unwritable or owned by another user; a path component of storeDir is an existing regular file; ENOSPC or read-only filesystem at store creation; Windows path/ACL problems.","commonSituations":"Daemon and desktop user mismatch on the profile directory; profile dir on a full or read-only volume; a stray file occupying a directory name in the store path (e.g. a file named like the store hash dir); migrated setups where the profile dir changed location.","solutions":["Check the storeDir from the error: verify each parent exists, is a directory, and is writable by the daemon user.","Remove any regular file occupying a component of the store path, then retry.","Free disk space / fix the read-only mount on the volume holding the profile dir.","Ensure the daemon runs as the user who owns the Multica profile directory."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if err := ensureWritableDir(filepath.Dir(storeDir)); err != nil {\n\treturn fmt.Errorf(\"memory store parent unusable: %w\", err)\n}\nif fi, err := os.Stat(storeDir); err == nil && !fi.IsDir() {\n\treturn fmt.Errorf(\"store path occupied by non-directory: %s\", storeDir)\n}","typeGuard":null,"tryCatchPattern":"if err := mountHermesMemories(hermesHome, storeDir, logger); err != nil {\n\tvar pe *os.PathError\n\tif errors.As(err, &pe) && strings.Contains(err.Error(), \"create hermes memory store\") {\n\t\tlog.Printf(\"memory store %s cannot be created — check ownership/space of the profile dir\", storeDir)\n\t}\n\treturn err\n}","preventionTips":["Run the daemon as the owner of the Multica profile directory.","Keep the profile dir on local disk with free space.","Never place regular files where store directories are expected."],"tags":["filesystem","permissions","memory-store","hermes","execenv"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}