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

  1. Read the wrapped OS error to identify which dir failed and why (the path is in the message)
  2. chown/chmod the instance root so the running user can create subdirectories (e.g. chown -R appuser /var/lib/picoclaw)
  3. Remove or rename any regular file occupying a required directory path
  4. 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

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


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/3299117ca843df92. Report an issue: GitHub.