fix: sort no longer panics on a value tagged as a number that is not one

sortableNodeArray.compare called panic(err) when parseInt64 or ParseFloat
failed, so a scalar tagged !!int or !!float whose value is not a number
crashed yq with a Go stack trace. An explicit tag in the input document is
enough to trigger it, no unusual expression needed.

Log a warning and compare the raw strings instead, matching the timestamp
branch a few lines above in the same function and the plain string fallback
the function already ends with. Values that do parse still compare
numerically.
This commit is contained in:
dualfroz committed 2026-09-03 14:15:29 +02:00
1 parent 8cf517a8c7
commit 472a5336be
2 files changed
+44 -4

No files matched your search

+8 -4
View File
@@ -160,11 +160,13 @@ func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateT
} else if lhsTag == "!!int" && rhsTag == "!!int" {
_, lhsNum, err := parseInt64(lhs.Value)
if err != nil {
panic(err)
log.Warningf("Could not parse %v as an int for sort, sorting by string instead: %v", lhs.Value, err)
return strings.Compare(lhs.Value, rhs.Value)
}
_, rhsNum, err := parseInt64(rhs.Value)
if err != nil {
panic(err)
log.Warningf("Could not parse %v as an int for sort, sorting by string instead: %v", rhs.Value, err)
return strings.Compare(lhs.Value, rhs.Value)
}
if lhsNum < rhsNum {
return -1
@@ -175,11 +177,13 @@ func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateT
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
if err != nil {
panic(err)
log.Warningf("Could not parse %v as a number for sort, sorting by string instead: %v", lhs.Value, err)
return strings.Compare(lhs.Value, rhs.Value)
}
rhsNum, err := strconv.ParseFloat(rhs.Value, 64)
if err != nil {
panic(err)
log.Warningf("Could not parse %v as a number for sort, sorting by string instead: %v", rhs.Value, err)
return strings.Compare(lhs.Value, rhs.Value)
}
if lhsNum == rhsNum {
return 0
+36
View File
@@ -180,6 +180,42 @@ var sortByOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::[-5000000000000000000, 5000000000000000000]\n",
},
},
{
skipDoc: true,
description: "Sort values tagged as ints that are not ints",
document: "[!!int b, !!int a]",
expression: `sort`,
expected: []string{
"D0, P[], (!!seq)::[!!int a, !!int b]\n",
},
},
{
skipDoc: true,
description: "Sort values tagged as floats that are not numbers",
document: "[!!float b, !!float a]",
expression: `sort`,
expected: []string{
"D0, P[], (!!seq)::[!!float a, !!float b]\n",
},
},
{
skipDoc: true,
description: "Sort a number against a value tagged as a number that is not one",
document: "[!!int zz, !!float 1.5]",
expression: `sort`,
expected: []string{
"D0, P[], (!!seq)::[!!float 1.5, !!int zz]\n",
},
},
{
skipDoc: true,
description: "Sort a map by a value tagged as an int that is not one",
document: "{a: !!int notanumber, b: !!int 3}",
expression: `to_entries | sort_by(.value) | from_entries`,
expected: []string{
"D0, P[], (!!map)::b: !!int 3\na: !!int notanumber\n",
},
},
}
func TestSortByOperatorScenarios(t *testing.T) {