{"record":{"id":"d3c3a62e38c38f35","repo":"charmbracelet/crush","slug":"failed-to-marshal-schema-w","errorCode":null,"errorMessage":"failed to marshal schema: %w","messagePattern":"failed to marshal schema: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/schema.go","lineNumber":26,"sourceCode":"\t\"github.com/charmbracelet/crush/internal/agent/hyper\"\n\t\"github.com/charmbracelet/crush/internal/config\"\n\t\"github.com/charmbracelet/crush/internal/discover\"\n\t\"github.com/invopop/jsonschema\"\n\t\"github.com/spf13/cobra\"\n)\n\nvar schemaCmd = &cobra.Command{\n\tUse:    \"schema\",\n\tShort:  \"Generate JSON schema for configuration\",\n\tLong:   \"Generate JSON schema for the crush configuration file\",\n\tHidden: true,\n\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\treflector := new(jsonschema.Reflector)\n\t\tschema := reflector.Reflect(&config.Config{})\n\t\tsetProviderTypeEnum(schema)\n\t\tbts, err := json.MarshalIndent(schema, \"\", \"  \")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to marshal schema: %w\", err)\n\t\t}\n\t\tfmt.Println(string(bts))\n\t\treturn nil\n\t},\n}\n\n// setProviderTypeEnum overwrites the provider `type` enum with the live set\n// of accepted values rather than a hand-maintained struct tag. The values\n// must match exactly what load.go validates against: the catwalk provider\n// types, the Charm Hyper type, and any locally-discovered providers that\n// self-register an enricher (e.g. ollama, omlx). Sourcing the enum here keeps\n// the published schema from drifting as provider types are added or renamed.\nfunc setProviderTypeEnum(schema *jsonschema.Schema) {\n\tdef, ok := schema.Definitions[\"ProviderConfig\"]\n\tif !ok || def.Properties == nil {\n\t\treturn\n\t}\n\ttypeProp, ok := def.Properties.Get(\"type\")","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/cmd/schema.go#L8-L44","documentation":"The `crush schema` command reflects config.Config into a JSON schema and marshals it with json.MarshalIndent. MarshalIndent only fails if the reflected schema contains values JSON cannot encode (unsupported types, invalid maps, or a custom MarshalJSON returning an error), making this a rare internal invariant failure.","triggerScenarios":"Running `crush schema` where the jsonschema.Reflector output for config.Config contains a value json.Marshal cannot serialize — e.g. a config type with a MarshalJSON method returning an error, or an exotic field type added to config.Config.","commonSituations":"Encountered after code changes to config.Config (new field with an unsupported/custom serializer) rather than by end users; corrupted toolchain or plugin injection is essentially unheard of.","solutions":["Rebuild/reinstall Crush to rule out a stale binary mismatched with the config package.","Identify the offending field in internal/config/config.go and give it a JSON-safe representation or valid MarshalJSON.","Upgrade to the latest Crush release where the schema generation bug may already be fixed.","Report the bug with the stack trace since this should be unreachable in normal operation."],"exampleFix":"// before\n// config field with broken custom marshaller\nfunc (p Provider) MarshalJSON() ([]byte, error) { return nil, errors.New(\"unsupported\") }\n// after\nfunc (p Provider) MarshalJSON() ([]byte, error) { return json.Marshal(string(p)) }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"bts, err := json.MarshalIndent(schema, \"\", \"  \")\nif err != nil {\n    return fmt.Errorf(\"failed to marshal schema: %w\", err) // inspect %w for the offending type\n}","preventionTips":["Keep custom JSON marshallers on config types trivially valid and unit-test them.","Test `crush schema` in CI whenever config.Config changes.","Round-trip the generated schema through json.Unmarshal in tests to catch encoding issues."],"tags":["json","schema","serialization"],"backgroundTag":"json-marshal-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}