sipeed/picoclaw · error
failed to load config: %w
Error message
failed to load config: %w
What it means
internal.LoadConfig (cmd/picoclaw/internal/helpers.go:27) failed while preparing the WeCom login flow. LoadConfig reads config.json from $PICOCLAW_CONFIG_PATH or ~/.picoclaw/config.json; a missing file returns defaults without error, so this error means the file exists but is unreadable, contains malformed JSON (reported via wrapJSONError diagnostics), or a config schema migration (V0→V1→V2→V3) failed.
Source
Thrown at cmd/picoclaw/internal/auth/wecom.go:116
return authWeComCmdWithScanner(context.Background(), os.Stdout, timeout, scanWeComQRCodeInteractive)
}
func authWeComCmdWithScanner(
ctx context.Context,
writer io.Writer,
timeout time.Duration,
scanner wecomQRScanner,
) error {
if scanner == nil {
return fmt.Errorf("wecom QR scanner is nil")
}
if writer == nil {
writer = os.Stdout
}
cfg, err := internal.LoadConfig()
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}
opts := defaultWeComQRFlowOptions(timeout)
opts.Writer = writer
botInfo, err := scanner(ctx, opts)
if err != nil {
return err
}
applyWeComAuthResult(cfg, botInfo)
if saveErr := config.SaveConfig(internal.GetConfigPath(), cfg); saveErr != nil {
return fmt.Errorf("failed to save config: %w", saveErr)
}
fmt.Fprintln(writer)
fmt.Fprintln(writer, "WeCom connected.")View on GitHub (pinned to 49183d7e8d)
Solutions
- Run the same load outside the flow (e.g. a status command) to see the detailed diagnostic line logged by LoadConfig, which names the exact JSON offset
- Validate config.json syntax with a JSON linter (e.g. jq . ~/.picoclaw/config.json)
- Fix permissions: chown the file to your user and ensure it is readable/writable (0600)
- If the file is a legacy version that fails migration, back it up and let picoclaw regenerate a default config, then re-add settings
- Check PICOCLAW_CONFIG_PATH / PICOCLAW_HOME env vars point at the intended file
Example fix
// before
cfg, err := internal.LoadConfig()
if err != nil {
return fmt.Errorf("failed to load config: %w", err)
}
// after: tell the user exactly which file failed
cfg, err := internal.LoadConfig()
if err != nil {
return fmt.Errorf("failed to load config %s: %w\nvalidate with: jq . %s", internal.GetConfigPath(), err, internal.GetConfigPath())
} Defensive patterns
Strategy: validation
Validate before calling
// Fail fast with a clear message before starting an interactive flow
path := internal.GetConfigPath()
if data, err := os.ReadFile(path); err == nil {
if !json.Valid(data) {
return fmt.Errorf("%s is not valid JSON — fix it before continuing", path)
}
} Type guard
func isConfigSyntaxError(err error) bool {
var syn *json.SyntaxError
return errors.As(err, &syn)
} Try / catch
cfg, err := internal.LoadConfig()
if err != nil {
if isConfigSyntaxError(err) {
return fmt.Errorf("config file has a JSON syntax error at offset — run: jq . %s", internal.GetConfigPath())
}
return fmt.Errorf("failed to load config: %w", err)
} Prevention
- Validate config.json with jq after every manual edit
- Keep config files user-owned; avoid running picoclaw under sudo
- Back up config.json before schema-migrating versions
When it happens
Trigger: Hand-edited config.json with invalid JSON; config file with wrong permissions or an unreadable path; a legacy version-0 config whose migration fails; PICOCLAW_CONFIG_PATH pointing at a directory or corrupt file.
Common situations: User manually edits ~/.picoclaw/config.json and leaves a trailing comma; an older picoclaw version wrote a schema the current migration cannot handle; file owned by root after running with sudo.
Related errors
- failed to save config: %w
- invalid WeCom QR generate URL: %w
- invalid WeCom QR query URL: %w
- invalid WeCom QR page URL: %w
- decode JSON response: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/3a18da070af9b506.
Report an issue: GitHub.