JanDeDobbeleer/oh-my-posh · error

failed to marshal template cache: %w

Error message

failed to marshal template cache: %w

What it means

buildDataDocument (backing `oh-my-posh config export data`) serializes the template cache's SimpleTemplate struct to JSON to build the "env" section. If json.Marshal on that struct fails, the command aborts with "failed to marshal template cache: %w". This is essentially a programming/struct-shape problem: the SimpleTemplate type contains data json.Marshal cannot represent.

Source

Thrown at src/cli/config_export_data.go:136

// writeDataOutput prints doc to stdout, or writes it to --output when set.
// Shared by the single-config path and the --themes merge path.
func writeDataOutput(doc []byte) {
	if outputData == "" {
		fmt.Println(string(doc))
		return
	}

	if err := os.WriteFile(cleanOutputPath(outputData), doc, 0o644); err != nil {
		exitcode = 666
		fmt.Println(err.Error())
	}
}

// Extracted from dataCmd's Run so it can be unit tested without a real environment.
func buildDataDocument(cfg *config.Config) ([]byte, error) {
	envRaw, err := json.Marshal(template.Cache.SimpleTemplate)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal template cache: %w", err)
	}

	var envFields map[string]json.RawMessage
	if err := json.Unmarshal(envRaw, &envFields); err != nil {
		return nil, fmt.Errorf("failed to marshal template cache: %w", err)
	}

	// SegmentsCache is internal cache plumbing, and Var is already covered
	// by the config's own "var" section - neither belongs in a recorded
	// data file.
	delete(envFields, "SegmentsCache")
	delete(envFields, "Var")

	segments := make(map[string]json.RawMessage)

	for _, block := range cfg.Blocks {
		for _, segment := range block.Segments {
			writer := segment.Writer()

View on GitHub (pinned to 0976794618)

Solutions

  1. Update/rebuild oh-my-posh from a clean checkout; this indicates a build or version mismatch in the template package
  2. Clear the device/cache state (oh-my-posh cache clear) and rerun the export
  3. If you develop oh-my-posh: inspect the wrapped error to find which SimpleTemplate field is unmarshalable and fix its type or add a MarshalJSON
  4. Report the wrapped error message upstream if it occurs on a released binary

Example fix

// before (field json.Marshal cannot encode)
type SimpleTemplate struct { Fn func() string `json:"fn"` }

// after (make the field marshalable or skip it)
type SimpleTemplate struct { FnName string `json:"fn"` }
Defensive patterns

Strategy: try-catch

Type guard

// Go: verify the template cache marshals to a JSON object before export
func templateCacheIsObject(v any) bool {
	raw, err := json.Marshal(v)
	return err == nil && len(raw) > 0 && raw[0] == '{'
}

Try / catch

doc, err := buildDataDocument(cfg)
if err != nil {
	if strings.Contains(err.Error(), "failed to marshal template cache") {
		fmt.Fprintf(os.Stderr, "template cache is not encodable: %v\n", err)
		os.Exit(1)
	}
	return err
}

Prevention

When it happens

Trigger: Running `oh-my-posh config export data` (or --themes/--sanitize merge path via recordThemeSanitized -> buildDataDocument) when template.Cache.SimpleTemplate holds a value json.Marshal rejects, such as an unexported-only shape change, an invalid value, or a struct containing a channel/func after an internal refactor.

Common situations: Developers working on the template package after changing SimpleTemplate fields; running a mismatched binary/version; custom builds where the template cache was populated with unexpected types. End users should essentially never see this.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of JanDeDobbeleer/oh-my-posh@0976794618 (2026-08-31). Data as JSON: /api/errors/ff2408d78bb02cf7. Report an issue: GitHub.