From 86a6f5b01365c6a8bea21b47831c356850649009 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 7 Jan 2026 09:40:27 +0100 Subject: [PATCH 1/4] structaccess.Get: return NotFoundError for nil case --- libs/structs/structaccess/get.go | 4 +++- libs/structs/structaccess/get_test.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/structs/structaccess/get.go b/libs/structs/structaccess/get.go index b42c3977d6..0b8cb36290 100644 --- a/libs/structs/structaccess/get.go +++ b/libs/structs/structaccess/get.go @@ -53,7 +53,9 @@ func getValue(v any, path *structpath.PathNode) (reflect.Value, error) { cur, ok = deref(cur) if !ok { // cannot proceed further due to nil encountered at current location - return reflect.Value{}, fmt.Errorf("%s: cannot access nil value", node.Parent().String()) + // There could be 2 cases: the type is correct but value is not found due to nil, in this case NotFoundError is 100% correct. + // It could also be that path up to nil is correct, but not after. We don't know because we stop there. In this case NotFoundError refers to path up to nil. + return reflect.Value{}, &NotFoundError{fmt.Sprintf("%s: cannot access nil value", node.Parent().String())} } if idx, isIndex := node.Index(); isIndex { diff --git a/libs/structs/structaccess/get_test.go b/libs/structs/structaccess/get_test.go index 593ae8a536..0a72a7a4a9 100644 --- a/libs/structs/structaccess/get_test.go +++ b/libs/structs/structaccess/get_test.go @@ -215,7 +215,7 @@ func runCommonTests(t *testing.T, obj any) { { name: "nil pointer access", path: "connection_not_set.id", - errFmt: "connection_not_set: cannot access nil value", + notFound: "connection_not_set: cannot access nil value", typeHasPath: true, }, { From 68d6b8b8ce3ba8a3e6583b74d001c3fafbded774 Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 7 Jan 2026 09:45:23 +0100 Subject: [PATCH 2/4] simplify test --- libs/structs/structaccess/get_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libs/structs/structaccess/get_test.go b/libs/structs/structaccess/get_test.go index 0a72a7a4a9..4055c374fa 100644 --- a/libs/structs/structaccess/get_test.go +++ b/libs/structs/structaccess/get_test.go @@ -268,12 +268,10 @@ func runCommonTests(t *testing.T, obj any) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { hasPathError := ValidateByString(reflect.TypeOf(obj), tt.path) - if tt.errFmt == "" && tt.notFound == "" || tt.typeHasPath { + if tt.errFmt == "" { require.NoError(t, hasPathError) - } else if tt.errFmt != "" { + } else { require.EqualError(t, hasPathError, tt.errFmt) - } else if tt.notFound != "" { - require.EqualError(t, hasPathError, tt.notFound) } got, err := GetByString(obj, tt.path) From e3c3452cbb9aa3b6ddf900e38bdea216483fd67b Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 7 Jan 2026 09:46:05 +0100 Subject: [PATCH 3/4] simplify test --- libs/structs/structaccess/get_test.go | 48 ++++++++++++--------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/libs/structs/structaccess/get_test.go b/libs/structs/structaccess/get_test.go index 4055c374fa..2544b02ae3 100644 --- a/libs/structs/structaccess/get_test.go +++ b/libs/structs/structaccess/get_test.go @@ -11,13 +11,12 @@ import ( // unexported global test case type type testCase struct { - name string - path string - want any - wantSelf bool - errFmt string - notFound string // if set, expect NotFoundError with this message - typeHasPath bool + name string + path string + want any + wantSelf bool + errFmt string + notFound string // if set, expect NotFoundError with this message } func testGet(t *testing.T, obj any, path string, want any) { @@ -197,10 +196,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "connection[0]: cannot index struct", }, { - name: "out of range index", - path: "items[5]", - notFound: "items[5]: index out of range, length is 2", - typeHasPath: true, + name: "out of range index", + path: "items[5]", + notFound: "items[5]: index out of range, length is 2", }, { name: "no json tag field should not be accessible", @@ -213,10 +211,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "items.id: cannot access key \"id\" on slice", }, { - name: "nil pointer access", - path: "connection_not_set.id", - notFound: "connection_not_set: cannot access nil value", - typeHasPath: true, + name: "nil pointer access", + path: "connection_not_set.id", + notFound: "connection_not_set: cannot access nil value", }, { name: "map non-string key type", @@ -224,10 +221,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "map_int.any: map key must be string, got int", }, { - name: "map missing key", - path: "labels.missing", - notFound: "labels.missing: key \"missing\" not found in map", - typeHasPath: true, + name: "map missing key", + path: "labels.missing", + notFound: "labels.missing: key \"missing\" not found in map", }, { name: "json dash ignored", @@ -247,10 +243,9 @@ func runCommonTests(t *testing.T, obj any) { want: "first", }, { - name: "key-value no match", - path: "items[id='missing']", - notFound: "items[id='missing']: no element found with id=\"missing\"", - typeHasPath: true, + name: "key-value no match", + path: "items[id='missing']", + notFound: "items[id='missing']: no element found with id=\"missing\"", }, { name: "key-value on non-slice", @@ -258,10 +253,9 @@ func runCommonTests(t *testing.T, obj any) { errFmt: "connection[id='abc']: cannot use key-value syntax on struct", }, { - name: "key-value field not found", - path: "items[missing='value']", - notFound: "items[missing='value']: no element found with missing=\"value\"", - typeHasPath: true, + name: "key-value field not found", + path: "items[missing='value']", + notFound: "items[missing='value']: no element found with missing=\"value\"", }, } From 4fbf794076beb6920c1c307c0a9734ea2e79937f Mon Sep 17 00:00:00 2001 From: Denis Bilenko Date: Wed, 7 Jan 2026 09:55:35 +0100 Subject: [PATCH 4/4] lint autofix --- libs/structs/structaccess/get.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/structs/structaccess/get.go b/libs/structs/structaccess/get.go index 0b8cb36290..0c35cf520d 100644 --- a/libs/structs/structaccess/get.go +++ b/libs/structs/structaccess/get.go @@ -55,7 +55,7 @@ func getValue(v any, path *structpath.PathNode) (reflect.Value, error) { // cannot proceed further due to nil encountered at current location // There could be 2 cases: the type is correct but value is not found due to nil, in this case NotFoundError is 100% correct. // It could also be that path up to nil is correct, but not after. We don't know because we stop there. In this case NotFoundError refers to path up to nil. - return reflect.Value{}, &NotFoundError{fmt.Sprintf("%s: cannot access nil value", node.Parent().String())} + return reflect.Value{}, &NotFoundError{node.Parent().String() + ": cannot access nil value"} } if idx, isIndex := node.Index(); isIndex {