Code change:
On , will fail to evaluate a filter when the member does not exist: For instance, if I were to execute Where not all in that namespace had the annotation, this would fail with the error message: This is confusing as it leads me to think more than one item was selected, so while it is not technically incorrect the error message is misleading. I would furthermore expect to more gracefully handle this case -- a missing here means that the filter should fail, not error.
What do you mean by ? How is it different from ?
As in, don't add that item to the list of items on which the following access is made. When I do: And there is no annotation on , I just get nothing back -- no error, just nothing. Similarly, i would have expected the filtered expression to give me the for all of the pods that have an annotation with value . That, anyway is what I understand the JSONPath syntax to mean. When you write You are saying:
cc since you authored and I'm not sure how we want to fix this.
Taking a look now
it looks like you need to do this (note that the annotations portion is wrapped by ): I wrote a unit test and it worked as expected. PTAL!
I'm pretty sure that was a typo on my end but let me check -- do you have a reproducer script?
I see an entirely different error today... weird:
Ok so you have 1 object with annotations, and 1 without. Let me look into that case.
Let me add another annotation to
No difference if both have annotations:
Ok, I'll have to test using kubectl
I'm the Origin bundled but I don't think there are any patches on JSONPath there:
I'm able to reproduce in the unit test when 1 object has annotations and the other does not, if allowMissingKeys is true for the jsonpath parser.
I see. Let me know if I can be of more help.
I think I have a fix. PR coming soon.
Possible

Related discussion:
text: } nodesTests := []jsonpathTest{ <del> {"range item", `{range .items[*]}{.metadata.name}, {end}{.kind}`, nodesData, "127.0.0.1, 127.0.0.2, List"}, {"range item with quote", `{range .items[*]}{.metadata.name}{"t"}{end}`, nodesData, "127.0.0.1t127.0.0.2t"}, </del> <ins> {"range item", `{range .items[*]}{.metadata.name}, {end}{.kind}`, nodesData, "127.0.0.1, 127.0.0.2, List", false}, {"range item with quote", `{range .items[*]}{.metadata.name}{"t"}{end}`, nodesData, "127.0.0.1t127.0.0.2t", false}, </ins> {"range addresss", `{.items[*].status.addresses[*].address}`, nodesData, <del> "127.0.0.1 127.0.0.2 127.0.0.3"}, </del> <ins> "127.0.0.1 127.0.0.2 127.0.0.3", false}, </ins> {"double range", `{range .items[*]}{range .status.addresses[*]}{.address}, {end}{end}`, nodesData, <del> "127.0.0.1, 127.0.0.2, 127.0.0.3, "}, {"item name", `{.items[*].metadata.name}`, nodesData, "127.0.0.1 127.0.0.2"}, </del> <ins> "127.0.0.1, 127.0.0.2, 127.0.0.3, ", false}, {"item name", `{.items[*].metadata.name}`, nodesData, "127.0.0.1 127.0.0.2", false}, </ins> {"union nodes capacity", `{.items[*]['metadata.name', 'status.capacity']}`, nodesData, <del> "127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]"}, </del> <ins> "127.0.0.1 127.0.0.2 map[cpu:4] map[cpu:8]", false}, </ins> {"range nodes capacity", `{range .items[*]}[{.metadata.name}, {.status.capacity}] {end}`, nodesData, <del> "[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] "}, {"user password", `{.users[?(@.name=="e2e")].user.password}`, &nodesData, "secret"}, {"hostname", `{.items[0].metadata.labels.kubernetes.io/hostname}`, &nodesData, "127.0.0.1"}, {"hostname filter", `{.items[?(@.metadata.labels.kubernetes.io/hostname=="127.0.0.1")].kind}`, &nodesData, "None"}, {"bool item", `{.items[?(@..ready==true)].metadata.name}`, &nodesData, "127.0.0.1"}, </del> <ins> "[127.0.0.1, map[cpu:4]] [127.0.0.2, map[cpu:8]] ", false}, {"user password", `{.users[?(@.name=="e2e")].user.password}`, &nodesData, "secret", false}, {"hostname", `{.items[0].metadata.labels.kubernetes.io/hostname}`, &nodesData, "127.0.0.1", false}, {"hostname filter", `{.items[?(@.metadata.labels.kubernetes.io/hostname=="127.0.0.1")].kind}`, &nodesData, "None", false}, {"bool item", `{.items[?(@..ready==true)].metadata.name}`, &nodesData, "127.0.0.1", false}, </ins> } testJSONPath(nodesTests, false, t) randomPrintOrderTests := []jsonpathTest{ <del> {"recursive name", "{..name}", nodesData, `127.0.0.1 127.0.0.2 myself e2e`}, </del> <ins> {"recursive name", "{..name}", nodesData, `127.0.0.1 127.0.0.2 myself e2e`, false}, </ins> } testJSONPathSortOutput(randomPrintOrderTests, t) } <ins> func TestFilterPartialMatchesSometimesMissingAnnotations(t *testing.T) { // for https://issues.k8s.io/45546 var input = []byte(`{ "kind": "List", "items": [ { "kind": "Pod", "metadata": { "name": "pod1", "annotations": { "color": "blue" } } }, { "kind": "Pod", "metadata": { "name": "pod2" } }, { "kind": "Pod", "metadata": { "name": "pod3", "annotations": { "color": "green" } } }, { "kind": "Pod", "metadata": { "name": "pod4", "annotations": { "color": "blue" } } } ] }`) var data interface{} err := json.Unmarshal(input, &data) if err != nil { t.Fatal(err) } testJSONPath( []jsonpathTest{ { "filter, should only match a subset, some items don't have annotations, tolerate missing items", `{.items[?(@.metadata.annotations.color=="blue")].metadata.name}`, data, "pod1 pod4", false, // expect no error }, }, true, // allow missing keys t, ) testJSONPath( []jsonpathTest{ { "filter, should only match a subset, some items don't have annotations, error on missing items", `{.items[?(@.metadata.annotations.color=="blue")].metadata.name}`, data, "", true, // expect an error }, }, false, // don't allow missing keys t, ) } </ins>