antonmedv/fx · warning

<error from json.Marshal of the theme export map> (panic(err

Error message

<error from json.Marshal of the theme export map> (panic(err))

What it means

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.

Source

Thrown at internal/theme/theme.go:444

		if len(matches) == 0 {
			return ""
		} else {
			return matches[1]
		}
	}
	var export = map[string][]string{}
	for _, name := range themeNames {
		t := themes[name]
		export[name] = append(export[name], extract(t.Syntax(placeholder)))
		export[name] = append(export[name], extract(t.Key(placeholder)))
		export[name] = append(export[name], extract(t.String(placeholder)))
		export[name] = append(export[name], extract(t.Number(placeholder)))
		export[name] = append(export[name], extract(t.Boolean(placeholder)))
		export[name] = append(export[name], extract(t.Null(placeholder)))
	}
	data, err := json.Marshal(export)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))
}

View on GitHub (pinned to 4f31cd3a0c)

Solutions

  1. Audit the values appended to export[name]; keep only strings, bools, nil, and other JSON-serializable types
  2. If custom types are needed, implement json.Marshaler on them
  3. Return the error instead of panicking so callers can report it cleanly

Example fix

// before
data, err := json.Marshal(export)
if err != nil {
	panic(err)
}
// after
data, err := json.Marshal(export)
if err != nil {
	return fmt.Errorf("marshaling theme export: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// ensure export map holds only serializable values before marshaling
for name, vals := range export {
	for _, v := range vals {
		if _, err := json.Marshal(v); err != nil {
			log.Fatalf("theme %q has non-serializable value: %v", name, err)
		}
	}
}

Try / catch

// wrap the panic if calling ExportThemes programmatically
func safeExport() (out string, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("ExportThemes panicked: %v", r)
		}
	}()
	ExportThemes()
	return "", nil
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of antonmedv/fx@4f31cd3a0c (2026-09-02). Data as JSON: /api/errors/7633f615df688004. Report an issue: GitHub.