{"record":{"id":"3299117ca843df92","repo":"sipeed/picoclaw","slug":"prepare-instance-dir-s-w","errorCode":null,"errorMessage":"prepare instance dir %s: %w","messagePattern":"prepare instance dir (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/isolation/runtime.go","lineNumber":81,"sourceCode":"\tdefer isolationMu.RUnlock()\n\treturn currentIsolation\n}\n\n// ResolveInstanceRoot resolves the instance root used to build the isolated\n// filesystem and redirected user environment.\nfunc ResolveInstanceRoot() (string, error) {\n\troot := filepath.Clean(config.GetHome())\n\tif root == \".\" {\n\t\treturn \"\", fmt.Errorf(\"instance root resolved to current directory\")\n\t}\n\treturn root, nil\n}\n\n// PrepareInstanceRoot creates the directories required by the isolation runtime.\nfunc PrepareInstanceRoot(root string) error {\n\tfor _, dir := range InstanceDirs(root) {\n\t\tif err := os.MkdirAll(dir, 0o755); err != nil {\n\t\t\treturn fmt.Errorf(\"prepare instance dir %s: %w\", dir, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// InstanceDirs returns the directories that must exist under the instance root\n// for isolation-aware child processes.\nfunc InstanceDirs(root string) []string {\n\tdirs := []string{\n\t\troot,\n\t\tfilepath.Join(root, \"skills\"),\n\t\tfilepath.Join(root, \"logs\"),\n\t\tfilepath.Join(root, \"cache\"),\n\t\tfilepath.Join(root, \"state\"),\n\t\tfilepath.Join(root, \"runtime-user-env\"),\n\t\tfilepath.Join(root, \"runtime-user-env\", \"home\"),\n\t\tfilepath.Join(root, \"runtime-user-env\", \"tmp\"),\n\t\tfilepath.Join(root, \"runtime-user-env\", \"config\"),","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/isolation/runtime.go#L63-L99","documentation":"PrepareInstanceRoot calls os.MkdirAll(dir, 0o755) for every directory returned by InstanceDirs(root) — the instance root plus skills/, logs/ and other runtime subdirectories. If any single MkdirAll fails, the error wraps the failing directory path and the underlying OS error, and preflight stops before any child process is launched.","triggerScenarios":"(1) EACCES: the instance root or a parent is owned by another user (e.g. root created it, app runs unprivileged); (2) ENOTDIR: a regular file exists where a directory component is required (root/logs is a file); (3) EROFS: instance root on a read-only mount; (4) ENAMETOOLONG or looped symlinks in the path; (5) disk/inode exhaustion during mkdir.","commonSituations":"First run after manual root creation with sudo leaving root-owned dirs; instance root pointed at a mounted volume with wrong ownership; a stray file named like one of the instance dirs; root placed on a read-only config mount; running the app as a different user than the one that owns ~/.picoclaw.","solutions":["Read the wrapped OS error to identify which dir failed and why (the path is in the message)","chown/chmod the instance root so the running user can create subdirectories (e.g. chown -R appuser /var/lib/picoclaw)","Remove or rename any regular file occupying a required directory path","Point PICOCLAW_HOME at a writable location or remount the volume read-write"],"exampleFix":"# before: root-owned instance dir\n$ ls -ld /var/lib/picoclaw\ndrwxr-xr-x 1 root root ... /var/lib/picoclaw\n\n# after\n# chown -R appuser:appuser /var/lib/picoclaw","handlingStrategy":"validation","validationCode":"// probe writability of the instance root before preflight\nfunc rootWritable(root string) bool {\n    probe := filepath.Join(root, \".write-probe\")\n    if err := os.WriteFile(probe, nil, 0o644); err != nil {\n        return false\n    }\n    _ = os.Remove(probe)\n    return true\n}","typeGuard":null,"tryCatchPattern":"if err := isolation.PrepareInstanceRoot(root); err != nil {\n    return fmt.Errorf(\"instance dirs uncreateable (check ownership/mounts under %s): %w\", root, err)\n}","preventionTips":["Create the instance root once at install time with the app user as owner","Keep the instance root off read-only mounts; check for stray files named like skills/ or logs/","Run the app under a stable uid that owns the instance root"],"tags":["filesystem","permissions","isolation","config"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}