JanDeDobbeleer/oh-my-posh · error

failed to parse segments for theme %s: %w

Error message

failed to parse segments for theme %s: %w

What it means

This error is thrown by recordThemeSanitized when the `segments` key (config.DataSegmentsKey) of a recorded theme cannot be unmarshalled into the segments structure. The document and env parsed, but the segments payload has an unexpected JSON shape. The underlying unmarshal error is wrapped with the theme path.

Source

Thrown at src/cli/config_export_data.go:249

	sanitized, err := sanitizeDataDocument(doc, cfg)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to sanitize theme %s: %w", themePath, err)
	}

	var root map[string]json.RawMessage
	if err := json.Unmarshal(sanitized, &root); err != nil {
		return nil, nil, fmt.Errorf("failed to parse recorded theme %s: %w", themePath, err)
	}

	if raw, ok := root[config.DataEnvKey]; ok {
		if err := json.Unmarshal(raw, &env); err != nil {
			return nil, nil, fmt.Errorf("failed to parse env for theme %s: %w", themePath, err)
		}
	}

	if raw, ok := root[config.DataSegmentsKey]; ok {
		if err := json.Unmarshal(raw, &segments); err != nil {
			return nil, nil, fmt.Errorf("failed to parse segments for theme %s: %w", themePath, err)
		}
	}

	return env, segments, nil
}

// countPopulatedLeaves parses raw and counts its non-zero-value leaves: a
// non-empty string, a non-zero number, true, or a non-empty array/map each
// count as 1; a leaf holding the zero value for its type (including null)
// counts as 0. Containers themselves are not counted, only what they hold -
// an empty array contributes 0, a 3-element array contributes the sum of
// its elements' own counts.
func countPopulatedLeaves(raw json.RawMessage) int {
	var v any
	if err := json.Unmarshal(raw, &v); err != nil {
		return 0
	}

View on GitHub (pinned to 0976794618)

Solutions

  1. Inspect the `segments` key in the theme file named in the error and restore the expected shape (objects per segment with correctly typed properties)
  2. Regenerate the merged fixture with `oh-my-posh config export data --themes <dir> --sanitize` rather than merging files manually
  3. Read the wrapped %w error to find the exact segment property with the wrong type and fix it
  4. If segment structs changed between versions, re-record all fixtures with the current binary

Example fix

// before: segments as a string
{ "segments": "text" }
// after
{ "segments": { "git": { "text": "main" } } }
Defensive patterns

Strategy: validation

Validate before calling

var root map[string]json.RawMessage
if err := json.Unmarshal(raw, &root); err != nil { return err }
segRaw, ok := root["segments"]
if ok {
    var segments map[string]any
    if err := json.Unmarshal(segRaw, &segments); err != nil {
        return fmt.Errorf("segments key must be an object: %w", err)
    }
}

Type guard

func hasWellFormedSegments(doc []byte) bool {
    var root struct { Segments map[string]json.RawMessage `json:"segments"` }
    return json.Unmarshal(doc, &root) == nil
}

Try / catch

env, segments, err := recordThemeSanitized(themePath)
if err != nil {
    var uerr *json.UnmarshalTypeError
    if errors.As(err, &uerr) {
        log.Fatalf("theme %s: segment field %s wrong type (want %s)", themePath, uerr.Field, uerr.Type)
    }
    return err
}

Prevention

When it happens

Trigger: Running `oh-my-posh config export data --themes <dir> --sanitize` where a theme's recorded `segments` entry is not the expected object/array shape (e.g. segments is a scalar, or segment entries have fields of the wrong type).

Common situations: A hand-merged or hand-edited fixture where segments were combined incorrectly; fixtures recorded by an older oh-my-posh whose segment structs changed (renamed or retyped properties); a merge script that overwrote the segments key with the wrong type.

Understand the failure class

Related errors


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