JanDeDobbeleer/oh-my-posh · error

failed to marshal segment %s: %w

Error message

failed to marshal segment %s: %w

What it means

While recording the export data document, each configured segment's writer is serialized via recordSegmentData. If marshaling a segment's data fails, buildDataDocument aborts naming the segment: "failed to marshal segment <key>: <reason>". It means one segment type produced data json.Marshal cannot encode (or recordSegmentData hit an internal error).

Source

Thrown at src/cli/config_export_data.go:161

	// 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()
			if writer == nil {
				continue
			}

			raw, methods, err := recordSegmentData(writer)
			if err != nil {
				return nil, fmt.Errorf("failed to marshal segment %s: %w", segment.DataKey(), err)
			}

			recorded := config.RecordedSegment{Data: raw, Methods: methods, Enabled: segment.Enabled}

			recordedRaw, err := json.Marshal(recorded)
			if err != nil {
				return nil, fmt.Errorf("failed to marshal segment %s: %w", segment.DataKey(), err)
			}

			key := segment.DataKey()
			if _, exists := segments[key]; exists {
				fmt.Fprintf(os.Stderr, "warning: multiple segments share the data key %q; the last one wins - add an alias to disambiguate\n", key)
			}

			segments[key] = recordedRaw
		}
	}

View on GitHub (pinned to 0976794618)

Solutions

  1. Identify the segment named in the message and check the wrapped cause for the exact field
  2. Update oh-my-posh; if recent, this may be a regression — report it with the wrapped error
  3. Temporarily disable the offending segment in the config to unblock the export
  4. For segment developers: give the offending field a json:"-" tag or a MarshalJSON implementation

Example fix

// before
type gitData struct { Hooks map[int]string `json:"hooks"` }

// after
type gitData struct { Hooks map[int]string `json:"-"` } // or map[string]string
Defensive patterns

Strategy: try-catch

Type guard

// Go: check segment data encodes cleanly before recording
func segmentDataEncodable(writer segments.SegmentWriter) bool {
	raw, _, err := recordSegmentData(writer)
	return err == nil && json.Valid(raw)
}

Try / catch

if err := runDataExport(cfg); err != nil {
	var segErr interface{ Unwrap() error }
	if strings.Contains(err.Error(), "failed to marshal segment") {
		fmt.Fprintf(os.Stderr, "offending segment identified in: %v\n", err)
		os.Exit(1)
	}
	return err
}

Prevention

When it happens

Trigger: Running `oh-my-posh config export data` with a config containing a segment whose writer data is unmarshalable — typically a map keyed by a non-string type, an invalid value, or a func/channel field in a segment's response struct.

Common situations: Buggy or experimental segment data after an oh-my-posh update; a custom config exercising a rarely recorded segment (e.g. odd API response shapes cached into a segment's data); developing a new segment with an unmarshalable field.

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/52111eb42a899807. Report an issue: GitHub.