sipeed/picoclaw · error
invalid expose_paths mode: %s
Error message
invalid expose_paths mode: %s
What it means
ValidateExposePaths accepts only the exact strings "ro" and "rw" as the mode of an expose_paths entry; anything else — including "read-only", "w", "RW", "rw," or the empty string — is rejected with this error echoing the offending value.
Source
Thrown at pkg/isolation/runtime.go:170
}
env := make([]string, 0, len(envMap))
for k, v := range envMap {
env = append(env, fmt.Sprintf("%s=%s", k, v))
}
cmd.Env = env
}
// ValidateExposePaths verifies the user-supplied path exposure rules before a
// child process is started.
func ValidateExposePaths(items []config.ExposePath) error {
seen := map[string]struct{}{}
for _, item := range items {
if item.Source == "" {
return fmt.Errorf("source is required")
}
if item.Mode != "ro" && item.Mode != "rw" {
return fmt.Errorf("invalid expose_paths mode: %s", item.Mode)
}
source := filepath.Clean(item.Source)
target := item.Target
if target == "" {
target = source
}
target = filepath.Clean(target)
if !filepath.IsAbs(source) || !filepath.IsAbs(target) {
return fmt.Errorf("source and target must be absolute paths")
}
if _, ok := seen[target]; ok {
return fmt.Errorf("duplicate expose_path target: %s", target)
}
seen[target] = struct{}{}
}
return nilView on GitHub (pinned to 49183d7e8d)
Solutions
- Use exactly ro or rw, lowercase, no whitespace
- If you copied options from another tool's volume syntax, strip its extras (z, Z, shared, etc.)
- Delete the mode key only if your config loader defaults it — as validated here, an absent mode that arrives as "" fails, so prefer setting it explicitly
Example fix
# before
isolation:
expose_paths:
- source: /home/me/project
mode: read-only
# after
isolation:
expose_paths:
- source: /home/me/project
mode: ro Defensive patterns
Strategy: type-guard
Validate before calling
for _, p := range cfg.Isolation.ExposePaths {
if !isValidExposeMode(p.Mode) {
return fmt.Errorf("expose_paths mode must be exactly \"ro\" or \"rw\", got %q", p.Mode)
}
} Type guard
func isValidExposeMode(mode string) bool {
return mode == "ro" || mode == "rw"
} Prevention
- Accept only the literal lowercase tokens ro/rw in docs and generators
- Do not port docker/Kubernetes volume flags verbatim — translate them to ro/rw first
When it happens
Trigger: Config written with a verbose or differently-cased permission word: mode: read-only, mode: readwrite, mode: w, or mode omitted entirely (empty string fails because "" is neither ro nor rw). The comparison is exact: no trimming, no case folding.
Common situations: Translating docker-compose volume options (rw/ro vs z/Z, consistent) or Kubernetes mount options into picoclaw config; users writing "read-only" out of habit; YAML quoting a value with a trailing space.
Related errors
- source is required
- source and target must be absolute paths
- duplicate expose_path target: %s
- ${label} must be a JSON object.
- ${label}.${key} must be a string.
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/4170b7266c6ac6d2.
Report an issue: GitHub.