{"record":{"id":"18e6a2aa142f745a","repo":"sipeed/picoclaw","slug":"error-loading-config-w-18e6a2","errorCode":null,"errorMessage":"error loading config: %w","messagePattern":"error loading config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/skills/command.go","lineNumber":27,"sourceCode":"\t\"github.com/sipeed/picoclaw/cmd/picoclaw/internal\"\n\t\"github.com/sipeed/picoclaw/pkg/skills\"\n)\n\ntype deps struct {\n\tworkspace    string\n\tskillsLoader *skills.SkillsLoader\n}\n\nfunc NewSkillsCommand() *cobra.Command {\n\tvar d deps\n\n\tcmd := &cobra.Command{\n\t\tUse:   \"skills\",\n\t\tShort: \"Manage skills\",\n\t\tPersistentPreRunE: func(cmd *cobra.Command, _ []string) error {\n\t\t\tcfg, err := internal.LoadConfig()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error loading config: %w\", err)\n\t\t\t}\n\n\t\t\td.workspace = cfg.WorkspacePath()\n\n\t\t\t// get global config directory and builtin skills directory\n\t\t\tglobalDir := filepath.Dir(internal.GetConfigPath())\n\t\t\tglobalSkillsDir := filepath.Join(globalDir, \"skills\")\n\t\t\tbuiltinSkillsDir := filepath.Join(globalDir, \"picoclaw\", \"skills\")\n\t\t\td.skillsLoader = skills.NewSkillsLoader(d.workspace, globalSkillsDir, builtinSkillsDir)\n\n\t\t\treturn nil\n\t\t},\n\t\tRunE: func(cmd *cobra.Command, _ []string) error {\n\t\t\treturn cmd.Help()\n\t\t},\n\t}\n\n\tloaderFn := func() (*skills.SkillsLoader, error) {","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/skills/command.go#L9-L45","documentation":"The skills command's PersistentPreRunE could not load picoclaw's configuration: internal.LoadConfig returned an error (malformed JSON, unreadable file, or failed validation), wrapped here. Every `picoclaw skills ...` subcommand aborts before its own logic runs.","triggerScenarios":"Running any `picoclaw skills` subcommand when the loaded config file is invalid JSON, unreadable due to permissions, or rejected by LoadConfig's validation (command.go:27).","commonSituations":"Hand-edited config.json with a trailing comma or unbalanced brace, file owned by root after a sudo run, or a config schema change after upgrading picoclaw.","solutions":["Read the wrapped cause — it distinguishes JSON syntax errors from permission and validation failures.","Validate the file mechanically (e.g. jq . <config.json>) and fix the reported syntax error.","Check permissions/ownership on the config path picoclaw reports.","If an upgrade changed the schema, re-init the config and re-apply your settings."],"exampleFix":"// before: { \"tools\": { \"skills\": { \"enabled\": true, } } }  // trailing comma\n// after:  { \"tools\": { \"skills\": { \"enabled\": true } } }","handlingStrategy":"validation","validationCode":"raw, err := os.ReadFile(internal.GetConfigPath())\nif err != nil {\n    return fmt.Errorf(\"cannot read config: %w\", err)\n}\nif !json.Valid(raw) {\n    return fmt.Errorf(\"config %s is not valid JSON\", internal.GetConfigPath())\n}","typeGuard":null,"tryCatchPattern":"cfg, err := internal.LoadConfig()\nif err != nil {\n    // surface the wrapped cause plus the config path so the user can fix it directly\n    return fmt.Errorf(\"error loading config: %w (check %s)\", err, internal.GetConfigPath())\n}","preventionTips":["Lint config.json in CI or pre-commit whenever anything edits it.","Back up config before schema-migrating picoclaw versions.","Prefer picoclaw's own config commands over hand-editing JSON."],"tags":["config","cli","json","go"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}