mikefarah/yq · critical

panic(err) on ParseFloat failure while sorting numeric value

Error message

panic(err) on ParseFloat failure while sorting numeric values

What it means

The sort compare function panics when comparing values tagged !!int/!!float (mixed) and strconv.ParseFloat fails on the left operand at operator_sort.go:176-179. This branch is reached when one side is !!float, so even a valid-looking int value gets re-parsed as float; any value string ParseFloat rejects (NaN-like words, underscores, hex, empty) triggers the panic inside sort.Less, killing the process.

Source

Thrown at pkg/yqlib/operator_sort.go:178

	} else if lhsTag == "!!int" && rhsTag == "!!int" {
		_, lhsNum, err := parseInt64(lhs.Value)
		if err != nil {
			panic(err)
		}
		_, rhsNum, err := parseInt64(rhs.Value)
		if err != nil {
			panic(err)
		}
		if lhsNum < rhsNum {
			return -1
		} else if lhsNum > rhsNum {
			return 1
		}
		return 0
	} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
		lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
		if err != nil {
			panic(err)
		}
		rhsNum, err := strconv.ParseFloat(rhs.Value, 64)
		if err != nil {
			panic(err)
		}
		if lhsNum == rhsNum {
			return 0
		} else if lhsNum < rhsNum {
			return -1
		}

		return 1
	}

	return strings.Compare(lhs.Value, rhs.Value)
}

View on GitHub (pinned to 8b5af0694b)

Solutions

  1. Scan the array before sorting and fix values whose tags are numeric but whose text is not ParseFloat-compatible: `yq '.[] | select(tag == "!!float" or tag == "!!int")'.
  2. Normalize YAML 1.1 hex/underscore literals to decimal, or retag them !!str for lexicographic sort: `sort_by(.v | tag="!!str")`.
  3. Replace empty/placeholder numerics with real numbers or strings before sorting.
  4. Force the whole field to !!str when numeric fidelity is not required, avoiding both numeric branches entirely.
  5. Upgrade yq so ParseFloat failures degrade to string comparison instead of panicking.

Example fix

# before
yq 'sort_by(.score)' m.yaml   # .score: [1.5, 0x1F] -> ParseFloat("0x1F") panics

# after
yq '(.score[] | select(tag == "!!int" and (. =~ "^0x"))) |= (tag="!!str")' m.yaml | yq 'sort_by(.score)'
Defensive patterns

Strategy: validation

Validate before calling

# find numeric-tagged values Go ParseFloat would reject
yq '.[] | select(tag == "!!int" or tag == "!!float") | select(test("^[-+]?([0-9]*\\.)?[0-9]+([eE][-+]?[0-9]+)?$") | not)' m.yaml

Type guard

// Go: float parseability guard
func isParseableFloat(s string) bool {
    _, err := strconv.ParseFloat(s, 64)
    return err == nil
}

Try / catch

out, err := func() (out string, err error) {
    defer func() { if r := recover(); r != nil { err = fmt.Errorf("sort ParseFloat panic: %v", r) } }()
    out = runYq("sort_by(.score)")
    return
}()

Prevention

When it happens

Trigger: sort/sort_by on an array containing at least one !!float element alongside a node whose .Value cannot be parsed as a float64 despite its numeric tag: e.g. `"1.2.3"` tagged !!float, `""` tagged !!int, `0x1F` tagged !!int, or `Inf`/`NaN` spellings unsupported by ParseFloat.

Common situations: Mixing integers and floats in one array where one value is malformed; data converted from formats that allow hex/octal numeric literals (YAML 1.1 `0x1F`, `1_000`) which Go's ParseFloat rejects; empty-string placeholders tagged numeric by a pipeline; scientific-notation edge cases.

Related errors


AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05). Data as JSON: /api/errors/9393daaaa07fc2fd. Report an issue: GitHub.