JanDeDobbeleer/oh-my-posh · error

failed to marshal segment

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).

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.

Appendix: 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)