sipeed/picoclaw · error
prepare instance dir %s: %w
Error message
prepare instance dir %s: %w
What it means
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.
Source
Thrown at pkg/isolation/runtime.go:81
defer isolationMu.RUnlock()
return currentIsolation
}
// ResolveInstanceRoot resolves the instance root used to build the isolated
// filesystem and redirected user environment.
func ResolveInstanceRoot() (string, error) {
root := filepath.Clean(config.GetHome())
if root == "." {
return "", fmt.Errorf("instance root resolved to current directory")
}
return root, nil
}
// PrepareInstanceRoot creates the directories required by the isolation runtime.
func PrepareInstanceRoot(root string) error {
for _, dir := range InstanceDirs(root) {
if err := os.MkdirAll(dir, 0o755); err != nil {
return fmt.Errorf("prepare instance dir %s: %w", dir, err)
}
}
return nil
}
// InstanceDirs returns the directories that must exist under the instance root
// for isolation-aware child processes.
func InstanceDirs(root string) []string {
dirs := []string{
root,
filepath.Join(root, "skills"),
filepath.Join(root, "logs"),
filepath.Join(root, "cache"),
filepath.Join(root, "state"),
filepath.Join(root, "runtime-user-env"),
filepath.Join(root, "runtime-user-env", "home"),
filepath.Join(root, "runtime-user-env", "tmp"),
filepath.Join(root, "runtime-user-env", "config"),View on GitHub (pinned to 49183d7e8d)
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
Example fix
# before: root-owned instance dir $ ls -ld /var/lib/picoclaw drwxr-xr-x 1 root root ... /var/lib/picoclaw # after # chown -R appuser:appuser /var/lib/picoclaw
Defensive patterns
Strategy: validation
Validate before calling
// probe writability of the instance root before preflight
func rootWritable(root string) bool {
probe := filepath.Join(root, ".write-probe")
if err := os.WriteFile(probe, nil, 0o644); err != nil {
return false
}
_ = os.Remove(probe)
return true
} Try / catch
if err := isolation.PrepareInstanceRoot(root); err != nil {
return fmt.Errorf("instance dirs uncreateable (check ownership/mounts under %s): %w", root, err)
} Prevention
- 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
When it happens
Trigger: (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.
Common situations: 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.
Related errors
- failed to save config: %w
- failed to save config: %w
- local command %q is not executable
- failed to read security config: %w
- instance root resolved to current directory
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/3299117ca843df92.
Report an issue: GitHub.