JanDeDobbeleer/oh-my-posh · error

failed to parse env for theme %s: %w

Error message

failed to parse env for theme %s: %w

What it means

This error is thrown by recordThemeSanitized when the `env` key (config.DataEnvKey) inside a recorded/sanitized theme document cannot be unmarshalled into the env structure. The theme parsed fine at the top level, but the value under the env key is not the expected JSON shape. It wraps the underlying unmarshal error with the theme path.

Source

Thrown at src/cli/config_export_data.go:243

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

	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.

View on GitHub (pinned to 0976794618)

Solutions

  1. Open the theme/data file named in the message and inspect the `env` key: it must be a JSON object with correctly typed fields
  2. Regenerate the fixture with `oh-my-posh config export data --themes <dir> --sanitize` from a clean checkout instead of hand-editing it
  3. If a schema migration changed env field types, delete the stale fixture and re-record it with the current binary
  4. Check the underlying %w error for the exact JSON field/type mismatch and correct that field

Example fix

// before: env with wrong type
{ "env": ["SHELL=bash"] }
// after
{ "env": { "SHELL": "bash" } }
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

func hasWellFormedEnv(doc []byte) bool {
    var root struct { Env map[string]json.RawMessage `json:"env"` }
    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: field %s has wrong type (want %s): %v", themePath, uerr.Field, uerr.Type, uerr)
    }
    return err
}

Prevention

When it happens

Trigger: Running `oh-my-posh config export data --themes <dir> --sanitize` where a theme's recorded `env` entry is not an object matching the env schema (e.g. env is a string, array, or contains fields of the wrong type).

Common situations: A data fixture was edited by hand and the env block's structure was changed; a fixture generated by an older oh-my-posh version has an env layout that no longer matches current struct fields (e.g. a field changed from string to number).

Understand the failure class

Related errors


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