charmbracelet/crush · error
failed to marshal schema: %w
Error message
failed to marshal schema: %w
What it means
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.
Source
Thrown at internal/cmd/schema.go:26
"github.com/charmbracelet/crush/internal/agent/hyper"
"github.com/charmbracelet/crush/internal/config"
"github.com/charmbracelet/crush/internal/discover"
"github.com/invopop/jsonschema"
"github.com/spf13/cobra"
)
var schemaCmd = &cobra.Command{
Use: "schema",
Short: "Generate JSON schema for configuration",
Long: "Generate JSON schema for the crush configuration file",
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
reflector := new(jsonschema.Reflector)
schema := reflector.Reflect(&config.Config{})
setProviderTypeEnum(schema)
bts, err := json.MarshalIndent(schema, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal schema: %w", err)
}
fmt.Println(string(bts))
return nil
},
}
// setProviderTypeEnum overwrites the provider `type` enum with the live set
// of accepted values rather than a hand-maintained struct tag. The values
// must match exactly what load.go validates against: the catwalk provider
// types, the Charm Hyper type, and any locally-discovered providers that
// self-register an enricher (e.g. ollama, omlx). Sourcing the enum here keeps
// the published schema from drifting as provider types are added or renamed.
func setProviderTypeEnum(schema *jsonschema.Schema) {
def, ok := schema.Definitions["ProviderConfig"]
if !ok || def.Properties == nil {
return
}
typeProp, ok := def.Properties.Get("type")View on GitHub (pinned to 7944b8e522)
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.
Example fix
// before
// config field with broken custom marshaller
func (p Provider) MarshalJSON() ([]byte, error) { return nil, errors.New("unsupported") }
// after
func (p Provider) MarshalJSON() ([]byte, error) { return json.Marshal(string(p)) } Defensive patterns
Strategy: try-catch
Try / catch
bts, err := json.MarshalIndent(schema, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal schema: %w", err) // inspect %w for the offending type
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed to decode workspaces: %w
- failed to decode messages: %w
- failed to marshal provider data: %w
- marshal request: %w
- failed to decode response: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/d3c3a62e38c38f35.
Report an issue: GitHub.