{"record":{"id":"c46dab778cba8de4","repo":"gastownhall/beads","slug":"repos-section-is-not-a-map","errorCode":null,"errorMessage":"repos section is not a map","messagePattern":"repos section is not a map","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/repos.go","lineNumber":54,"sourceCode":"\tdata, err := os.ReadFile(configPath) // #nosec G304 - config file path from caller\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn &ReposConfig{}, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to read config.yaml: %w\", err)\n\t}\n\n\t// Parse into a generic map to extract repos section\n\tvar cfg map[string]interface{}\n\tif err := yaml.Unmarshal(data, &cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse config.yaml: %w\", err)\n\t}\n\n\trepos := &ReposConfig{}\n\tif reposRaw, ok := cfg[\"repos\"]; ok && reposRaw != nil {\n\t\treposMap, ok := reposRaw.(map[string]interface{})\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"repos section is not a map\")\n\t\t}\n\n\t\tif primary, ok := reposMap[\"primary\"].(string); ok {\n\t\t\trepos.Primary = primary\n\t\t}\n\n\t\tif additional, ok := reposMap[\"additional\"]; ok && additional != nil {\n\t\t\tswitch v := additional.(type) {\n\t\t\tcase []interface{}:\n\t\t\t\tfor _, item := range v {\n\t\t\t\t\tif str, ok := item.(string); ok {\n\t\t\t\t\t\trepos.Additional = append(repos.Additional, str)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/config/repos.go#L36-L72","documentation":"GetReposFromYAML expects the top-level `repos` key in config.yaml to be a mapping (with optional `primary` and `additional` keys). When `repos:` parses to something else — a string, number, or list — the type assertion to map[string]interface{} fails and this error is returned.","triggerScenarios":"Calling GetReposFromYAML (via AddRepo/RemoveRepo/ListRepos) with a config.yaml containing e.g. `repos: foo`, `repos: [a, b]`, or `repos: 3` instead of `repos:\\n  primary: ...\\n  additional: [...]`.","commonSituations":"Hand-editing the config and writing the repo path directly under `repos:` instead of nesting it; misreading the schema and using a list of repos; a malformed merge that flattened the section.","solutions":["Restructure the repos section as a mapping with primary/additional keys.","Example correct shape: repos:\\n  primary: \".\"\\n  additional: [\"../other-repo\"].","Re-run the command after fixing; or delete the repos key and let `bd repo add` regenerate it."],"exampleFix":"// before\nrepos: ../other-repo\n// after\nrepos:\n  primary: \".\"\n  additional:\n    - \"../other-repo\"","handlingStrategy":"type-guard","validationCode":"var cfg map[string]interface{}\nif data, err := os.ReadFile(configPath); err == nil {\n    if yaml.Unmarshal(data, &cfg) == nil {\n        if raw, ok := cfg[\"repos\"]; ok && raw != nil {\n            if _, ok := raw.(map[string]interface{}); !ok {\n                return fmt.Errorf(\"repos must be a mapping with primary/additional keys\")\n            }\n        }\n    }\n}","typeGuard":"func reposIsMap(cfg map[string]interface{}) bool {\n    raw, ok := cfg[\"repos\"]\n    if !ok || raw == nil { return true }\n    _, ok = raw.(map[string]interface{})\n    return ok\n}","tryCatchPattern":"repos, err := config.GetReposFromYAML(configPath)\nif err != nil && strings.Contains(err.Error(), \"repos section is not a map\") {\n    return fmt.Errorf(\"fix `repos:` in %s to a mapping: repos:\\\\n  primary: ...\", configPath)\n}","preventionTips":["Nest primary/additional under repos:; never put a value directly after repos:.","Use `bd repo add`/`bd repo remove` instead of hand-editing the repos section.","Keep a schema example of config.yaml in your project docs."],"tags":["config","yaml","schema","type-mismatch"],"backgroundTag":"config-schema-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}