{"record":{"id":"21940eb526812c74","repo":"gastownhall/beads","slug":"parsing-legacy-config-w","errorCode":null,"errorMessage":"parsing legacy config: %w","messagePattern":"parsing legacy config: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/configfile.go","lineNumber":100,"sourceCode":"func Load(beadsDir string) (*Config, error) {\n\tconfigPath := ConfigPath(beadsDir)\n\n\tdata, err := os.ReadFile(configPath) // #nosec G304 - controlled path from config\n\tif os.IsNotExist(err) {\n\t\t// Try legacy config.json location (migration path)\n\t\tlegacyPath := filepath.Join(beadsDir, \"config.json\")\n\t\tdata, err = os.ReadFile(legacyPath) // #nosec G304 - controlled path from config\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil, nil\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"reading legacy config: %w\", err)\n\t\t}\n\n\t\t// Migrate: parse legacy config, save as metadata.json, remove old file\n\t\tvar cfg Config\n\t\tif err := json.Unmarshal(data, &cfg); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"parsing legacy config: %w\", err)\n\t\t}\n\n\t\t// Save to new location\n\t\tif err := cfg.Save(beadsDir); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"migrating config to metadata.json: %w\", err)\n\t\t}\n\n\t\t// Remove legacy file (best effort: migration already saved to new location)\n\t\t_ = os.Remove(legacyPath)\n\n\t\treturn &cfg, nil\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"reading config: %w\", err)\n\t}\n\n\tvar cfg Config\n\tif err := json.Unmarshal(data, &cfg); err != nil {","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/configfile.go#L82-L118","documentation":"Load() in internal/configfile reads .beads/metadata.json; if absent, it falls back to the legacy config.json and migrates it. This error wraps a json.Unmarshal failure on that legacy file, meaning the old config.json exists but is not valid JSON (or has incompatible types for Config fields). Load aborts rather than silently dropping workspace settings.","triggerScenarios":"Calling configfile.Load(beadsDir) when metadata.json is missing, config.json exists, and config.json contains malformed JSON (truncated write, hand-edited syntax error, non-JSON content) or fields whose JSON types don't match Config (e.g. \"database\": 123).","commonSituations":"Workspaces created by old bd versions migrated after a manual edit; interrupted writes to config.json from a crash or full disk; a user placing notes or YAML in config.json; older metadata fields with changed types.","solutions":["Validate/repair config.json with a JSON linter (jq . config.json) and fix syntax errors","Check field value types against the Config struct in internal/configfile/configfile.go (e.g. database must be a string)","Restore config.json from backup or version control","Delete config.json and recreate config via bd init (migration will start fresh with defaults)"],"exampleFix":"// before\n{ \"database\": 123, }   // trailing comma, wrong type\n// after\n{ \"database\": \"beads.db\" }","handlingStrategy":"validation","validationCode":"data, err := os.ReadFile(filepath.Join(beadsDir, \"config.json\"))\nif err == nil {\n\tvar probe map[string]any\n\tif jerr := json.Unmarshal(data, &probe); jerr != nil {\n\t\treturn fmt.Errorf(\"legacy config.json is not valid JSON, fix before running bd: %w\", jerr)\n\t}\n}","typeGuard":"func isJSON(data []byte) bool {\n\tvar v any\n\treturn json.Unmarshal(data, &v) == nil\n}","tryCatchPattern":"cfg, err := configfile.Load(beadsDir)\nif err != nil {\n\tvar syntaxErr *json.SyntaxTypeError\n\tvar typeErr *json.UnmarshalTypeError\n\tswitch {\n\tcase errors.As(err, &syntaxErr):\n\t\t// point user at config.json offset in syntaxErr.Offset\n\tcase errors.As(err, &typeErr):\n\t\t// wrong type at typeErr.Field\n\t}\n\treturn err\n}","preventionTips":["Never hand-edit config.json while bd may run concurrently","Validate JSON after any manual edit (jq . config.json)","Upgrade bd fully so legacy migration completes once and removes config.json","Keep .beads under version control to restore corrupt files"],"tags":["json","config","migration","parsing"],"backgroundTag":"invalid-config-json","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}