{"record":{"id":"7633f615df688004","repo":"antonmedv/fx","slug":"error-from-json-marshal-of-the-theme-export-map","errorCode":null,"errorMessage":"<error from json.Marshal of the theme export map> (panic(err))","messagePattern":"<error from json\\.Marshal of the theme export map> \\(panic\\(err\\)\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/theme/theme.go","lineNumber":444,"sourceCode":"\t\tif len(matches) == 0 {\n\t\t\treturn \"\"\n\t\t} else {\n\t\t\treturn matches[1]\n\t\t}\n\t}\n\tvar export = map[string][]string{}\n\tfor _, name := range themeNames {\n\t\tt := themes[name]\n\t\texport[name] = append(export[name], extract(t.Syntax(placeholder)))\n\t\texport[name] = append(export[name], extract(t.Key(placeholder)))\n\t\texport[name] = append(export[name], extract(t.String(placeholder)))\n\t\texport[name] = append(export[name], extract(t.Number(placeholder)))\n\t\texport[name] = append(export[name], extract(t.Boolean(placeholder)))\n\t\texport[name] = append(export[name], extract(t.Null(placeholder)))\n\t}\n\tdata, err := json.Marshal(export)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(string(data))\n}\n","sourceCodeStart":426,"sourceCodeEnd":448,"githubUrl":"https://github.com/antonmedv/fx/blob/4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe/internal/theme/theme.go#L426-L448","documentation":"ExportThemes builds a map of theme data and serializes it with json.Marshal. If marshaling fails, it panics with the raw error instead of returning it. In practice json.Marshal of a map[string][]string built from well-typed theme extractors cannot fail, so this panic indicates an unexpected type reached the export map.","triggerScenarios":"json.Marshal returns an error for the export map — e.g. an unsupported value type (channel, func, cyclic structure) was appended to export[name] by a change to the extract() calls in ExportThemes.","commonSituations":"A contributor modifies ExportThemes to embed a non-serializable value (e.g. a func or a channel) into the export map; future theme entries holding custom types without MarshalJSON.","solutions":["Audit the values appended to export[name]; keep only strings, bools, nil, and other JSON-serializable types","If custom types are needed, implement json.Marshaler on them","Return the error instead of panicking so callers can report it cleanly"],"exampleFix":"// before\ndata, err := json.Marshal(export)\nif err != nil {\n\tpanic(err)\n}\n// after\ndata, err := json.Marshal(export)\nif err != nil {\n\treturn fmt.Errorf(\"marshaling theme export: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// ensure export map holds only serializable values before marshaling\nfor name, vals := range export {\n\tfor _, v := range vals {\n\t\tif _, err := json.Marshal(v); err != nil {\n\t\t\tlog.Fatalf(\"theme %q has non-serializable value: %v\", name, err)\n\t\t}\n\t}\n}","typeGuard":null,"tryCatchPattern":"// wrap the panic if calling ExportThemes programmatically\nfunc safeExport() (out string, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"ExportThemes panicked: %v\", r)\n\t\t}\n\t}()\n\tExportThemes()\n\treturn \"\", nil\n}","preventionTips":["Keep the export map typed as map[string][]string or similar JSON-safe types","Require json.Marshaler on any custom theme value type","Add a unit test that marshals the export map for every built-in theme"],"tags":["go","panic","json-marshal","theme"],"backgroundTag":"json-unsupported-type","analyzedSha":"4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe","analyzedAt":"2026-09-02T02:17:47.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}