{"record":{"id":"084bbb6471565413","repo":"gastownhall/beads","slug":"unable-to-parse-plugin-file-w","errorCode":null,"errorMessage":"unable to parse plugin file: %w","messagePattern":"unable to parse plugin file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/doctor/claude.go","lineNumber":558,"sourceCode":"\n\t// Path to installed_plugins.json\n\tpluginPath := filepath.Join(homeDir, \".claude\", \"plugins\", \"installed_plugins.json\")\n\n\t// Read plugin file\n\tdata, err := os.ReadFile(pluginPath) // #nosec G304 - path is controlled\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn \"\", false, nil\n\t\t}\n\t\treturn \"\", false, fmt.Errorf(\"unable to read plugin file: %w\", err)\n\t}\n\n\t// First, determine the format version\n\tvar versionCheck struct {\n\t\tVersion int `json:\"version\"`\n\t}\n\tif err := json.Unmarshal(data, &versionCheck); err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"unable to parse plugin file: %w\", err)\n\t}\n\n\t// Handle version 2 format (GH#741): plugins map contains arrays\n\tif versionCheck.Version == 2 {\n\t\tvar pluginDataV2 struct {\n\t\t\tPlugins map[string][]struct {\n\t\t\t\tVersion string `json:\"version\"`\n\t\t\t\tScope   string `json:\"scope\"`\n\t\t\t} `json:\"plugins\"`\n\t\t}\n\t\tif err := json.Unmarshal(data, &pluginDataV2); err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"unable to parse plugin file v2: %w\", err)\n\t\t}\n\n\t\t// Look for beads plugin - take first entry from the array\n\t\tif entries, ok := pluginDataV2.Plugins[\"beads@beads-marketplace\"]; ok && len(entries) > 0 {\n\t\t\treturn entries[0].Version, true, nil\n\t\t}","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/doctor/claude.go#L540-L576","documentation":"After reading installed_plugins.json, GetClaudePluginVersion first unmarshals it to detect the format version. If the file is not valid JSON at all, this error wraps the json.Unmarshal failure, indicating the plugin manifest is malformed.","triggerScenarios":"GetClaudePluginVersion (via CheckClaudePlugin) when the installed_plugins.json content fails json.Unmarshal — empty file, truncated write, or arbitrary non-JSON bytes — at cmd/bd/doctor/claude.go:558.","commonSituations":"A Claude plugin update was interrupted mid-write leaving a truncated/empty file; the file was hand-edited and corrupted; another tool overwrote it with logs or binary data.","solutions":["Inspect the file (cat ~/.claude/plugins/installed_plugins.json) and fix the JSON syntax","Delete the corrupt file and reinstall the beads Claude plugin so Claude regenerates it","Restart the Claude client/plugin marketplace to trigger a clean rewrite of the manifest","Validate with a JSON linter (jq . < file) before rerunning bd doctor"],"exampleFix":"# before\n$ cat ~/.claude/plugins/installed_plugins.json   # empty or truncated\n# after\nrm ~/.claude/plugins/installed_plugins.json\n# reinstall beads plugin via Claude, then rerun bd doctor","handlingStrategy":"validation","validationCode":"import \"encoding/json\", \"os\"\nfunc manifestIsValid(home string) error {\n\tp := filepath.Join(home, \".claude\", \"plugins\", \"installed_plugins.json\")\n\tdata, err := os.ReadFile(p)\n\tif err != nil { return err }\n\tif len(data) == 0 { return errors.New(\"manifest is empty\") }\n\tvar v any\n\treturn json.Unmarshal(data, &v)\n}","typeGuard":null,"tryCatchPattern":"_, installed, err := GetClaudePluginVersion()\nif err != nil && strings.Contains(err.Error(), \"unable to parse plugin file:\") {\n\tlog.Printf(\"corrupt manifest: %v — reinstall plugin\", err)\n\treturn nil\n}","preventionTips":["Never hand-edit installed_plugins.json while Claude is running","Validate JSON with jq before saving manual changes","Reinstall the plugin after crashes that may truncate writes","Back up the manifest before plugin updates"],"tags":["json","parse-error","claude-plugin","doctor"],"backgroundTag":"invalid-json-config","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}