{"record":{"id":"ecf0164b4f355d17","repo":"multica-ai/multica","slug":"remove-legacy-task-state-s-w","errorCode":null,"errorMessage":"remove legacy task state %s: %w","messagePattern":"remove legacy task state (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/daemon/execenv/hermes_home.go","lineNumber":595,"sourceCode":"\t\tif !fi.Mode().IsRegular() {\n\t\t\treturn fmt.Errorf(\"state marker is not a regular file: %s\", marker)\n\t\t}\n\t\treturn nil\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"stat state marker: %w\", err)\n\t}\n\n\tentries, err := os.ReadDir(hermesHome)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read overlay home: %w\", err)\n\t}\n\tfor _, entry := range entries {\n\t\tif !isHermesTaskLocalStateEntry(entry.Name()) {\n\t\t\tcontinue\n\t\t}\n\t\tpath := filepath.Join(hermesHome, entry.Name())\n\t\tif err := os.RemoveAll(path); err != nil {\n\t\t\treturn fmt.Errorf(\"remove legacy task state %s: %w\", path, err)\n\t\t}\n\t}\n\treturn writeFileAtomic(marker, []byte(\"task-local Hermes state\\n\"), 0o600)\n}\n\n// linkSharedHermesEntry symlinks dst → src, idempotent across Reuse: an existing\n// link already pointing at src is left alone; anything else is removed and\n// recreated so the overlay never drifts from the shared home. A dangling source\n// (a broken symlink in the user's home) is skipped, not failed. Directories use\n// createDirLink and files createFileLink so the Windows copy fallbacks match the\n// entry kind.\nfunc linkSharedHermesEntry(src, dst string) error {\n\tif fi, err := os.Lstat(dst); err == nil {\n\t\tif fi.Mode()&os.ModeSymlink != 0 {\n\t\t\tif target, err := os.Readlink(dst); err == nil && target == src {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/daemon/execenv/hermes_home.go#L577-L613","documentation":"prepareHermesTaskLocalState could not os.RemoveAll a legacy state.db or state.db-* sidecar (journal/WAL/shm) inside the generated overlay. These files are unsafe to reuse across daemon versions (they may be symlinks into the shared store or independent copies), so the migration deletes them and lets Hermes lazily recreate a fresh database; a failed delete fails the overlay.","triggerScenarios":"state.db is held open by a still-running Hermes process from a previous task; on Windows, SQLite byte-range locks on state.db-shm make deletion fail; read-only or foreign-owned files in the overlay.","commonSituations":"Upgrading the daemon while an old task's Hermes child is still alive; overlay reused across runs with different UIDs; Windows file-locking semantics on the SQLite sidecars.","solutions":["Stop lingering Hermes child processes from previous tasks (check process list for hermes on the same env), then retry.","On Windows, ensure the previous task fully exited before its overlay is reused (wait for handle release).","Fix ownership/permissions on the named path if it is foreign-owned or read-only.","Last resort: delete the entire overlay dir — state.db is task-local scratch and safely regenerable."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := prepareHermesTaskLocalState(hermesHome); err != nil {\n\tvar pe *os.PathError\n\tif errors.As(err, &pe) && strings.Contains(filepath.Base(pe.Path), \"state.db\") {\n\t\t// legacy SQLite files locked or undeletable: reset overlay (state.db is scratch)\n\t\tif rmErr := os.RemoveAll(hermesHome); rmErr == nil {\n\t\t\treturn prepareHermesTaskLocalState(hermesHome)\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Wait for previous Hermes child processes to exit before reusing an overlay.","On Windows, remember state.db-shm byte-range locks block deletion.","Treat state.db in overlays as disposable scratch; never preserve it across daemon upgrades."],"tags":["filesystem","sqlite","windows","hermes","execenv","file-locking"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}