JanDeDobbeleer/oh-my-posh · error

failed to parse segments in data file: %w

Error message

failed to parse segments in data file: %w

What it means

Thrown by dataFromRoot when the 'segments' key is present in a data file but is not a JSON object (map of string keys to values). The raw JSON for segments is unmarshaled into map[string]json.RawMessage; an array, string, number, or null fails and is wrapped with this message.

Source

Thrown at src/config/data.go:232

// once each has the same map[string]json.RawMessage shape in hand.
func dataFromRoot(root map[string]json.RawMessage) (*Data, error) {
	data := &Data{}

	if versionRaw, OK := root[DataVersionKey]; OK {
		if err := json.Unmarshal(versionRaw, &data.Version); err != nil {
			return nil, fmt.Errorf("failed to parse version in data file: %w", err)
		}
	}

	if env, OK := root[DataEnvKey]; OK {
		data.Env = env
	}

	if segmentsRaw, OK := root[DataSegmentsKey]; OK {
		var segments map[string]json.RawMessage

		if err := json.Unmarshal(segmentsRaw, &segments); err != nil {
			return nil, fmt.Errorf("failed to parse segments in data file: %w", err)
		}

		data.Segments = segments
	}

	return data, nil
}

// normalize re-marshals a generically decoded section (as produced by the
// YAML/TOML unmarshalers) to a map of raw JSON so the rest of the pipeline
// can treat all formats uniformly.
func normalize(generic map[string]any) (map[string]json.RawMessage, error) {
	root := make(map[string]json.RawMessage, len(generic))

	for key, value := range generic {
		b, err := json.Marshal(sanitize(value))
		if err != nil {
			return nil, err

View on GitHub (pinned to 0976794618)

Solutions

  1. Change segments to a keyed object: [segments] in TOML or segments: { key: {...} } in YAML
  2. Remove the segments key if no per-segment data is needed
  3. Cross-check against the main config format - theme segments arrays and data-file segment maps are different shapes

Example fix

// before (data.yaml)
segments:
  - os
  - path
// after
segments:
  os:
    template: "{{ .Icon }} "
Defensive patterns

Strategy: validation

Validate before calling

func segmentsIsObject(raw []byte) error {
	var root map[string]json.RawMessage
	if err := json.Unmarshal(raw, &root); err != nil { return err }
	if v, ok := root["segments"]; ok {
		var m map[string]json.RawMessage
		return json.Unmarshal(v, &m)
	}
	return nil
}

Type guard

func segmentsIsObject(root map[string]json.RawMessage) bool {
	var m map[string]json.RawMessage
	v, ok := root["segments"]
	return ok && json.Unmarshal(v, &m) == nil && m != nil
}

Try / catch

data, err := config.LoadData(path)
if err != nil && strings.Contains(err.Error(), "failed to parse segments") {
	return fmt.Errorf("segments must be a keyed object, not a list: %w", err)
}

Prevention

When it happens

Trigger: Calling LoadData or ParseData where the segments key holds a non-object: segments = [] in TOML, segments: - a in YAML (a list), or segments: "text"; note null also fails since it cannot unmarshal into map[string]json.RawMessage.

Common situations: Mistakenly defining segments as a list (as in the main theme config where segments is an array) instead of a keyed map; a merge/format-conversion tool reshaping segments; hand-written YAML indentation producing a list.

Understand the failure class

Related errors


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