sipeed/picoclaw · error
failed to save config: %w
Error message
failed to save config: %w
What it means
The serialized document already passed schema validation, but config.SaveConfig could not persist it (helpers.go:122-124). This is a filesystem-level failure: permission denied on the config file or directory, missing parent directory, disk full, or a failed atomic temp-write/rename.
Source
Thrown at cmd/picoclaw/internal/mcp/helpers.go:123
func saveValidatedConfig(cfg *config.Config) error {
if cfg == nil {
return fmt.Errorf("config is nil")
}
normalizedCfg := normalizedConfigForSave(cfg)
data, err := json.Marshal(normalizedCfg)
if err != nil {
return fmt.Errorf("failed to serialize config: %w", err)
}
if err := validateConfigDocument(data); err != nil {
return err
}
if err := config.SaveConfig(internal.GetConfigPath(), normalizedCfg); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
return nil
}
func normalizedConfigForSave(cfg *config.Config) *config.Config {
clone := *cfg
if cfg.Tools.MCP.Servers == nil {
return &clone
}
clone.Tools = cfg.Tools
clone.Tools.MCP = cfg.Tools.MCP
clone.Tools.MCP.Servers = make(map[string]config.MCPServerConfig, len(cfg.Tools.MCP.Servers))
for name, server := range cfg.Tools.MCP.Servers {
if server.Type != "" {
server.Type = config.NormalizeMCPTransportType(server.Type)
}View on GitHub (pinned to 49183d7e8d)
Solutions
- Check permissions and ownership of the config path and its directory; fix with chown/chmod
- Confirm the filesystem is writable (mount | grep <path>) and disk has space (df -h)
- Remove stale .tmp/.bak artifacts next to the config left by an interrupted save, then retry
Example fix
# before: config owned by root after sudo use # after sudo chown -R "$USER" ~/.config/picoclaw picoclaw mcp list
Defensive patterns
Strategy: try-catch
Validate before calling
cfgDir=$(dirname "$cfgPath")
[ -w "$cfgDir" ] || { echo "config dir not writable: $cfgDir" >&2; exit 1; }
df -h "$cfgDir" | tail -1 # confirm space Try / catch
if err := saveCmd.Execute(); err != nil {
if strings.Contains(err.Error(), "failed to save config") {
// underlying error is wrapped; check for fs errors
if errors.Is(err, fs.ErrPermission) {
fmt.Fprintln(os.Stderr, "fix permissions on the config directory and retry")
}
if errors.Is(err, fs.ErrSpace /* or ENOSPC via syscall */) {
fmt.Fprintln(os.Stderr, "disk full — free space and retry")
}
}
} Prevention
- Keep the config directory user-owned (avoid mixing sudo and normal runs)
- Monitor disk space on machines that write configs frequently
- Clean up stale temp files next to the config after crashed saves
When it happens
Trigger: Read-only $HOME or config dir; config file owned by root after earlier sudo use; disk exhausted; leftover temp file from a crashed write blocking rename.
Common situations: Running the CLI under sudo once so the config becomes root-owned; CI containers with read-only mounts; full disks in dev VMs.
Related errors
- local command %q is not executable
- failed to save config: %w
- reset failed: %w
- failed to load config: %w
- failed to stat local command %q: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/8114a39ac1750fbf.
Report an issue: GitHub.