From 386a24c1e749649273ac5a25e33fd0e7634d23a9 Mon Sep 17 00:00:00 2001 From: bejaratommy Date: Fri, 19 Jun 2026 10:08:05 +0000 Subject: [PATCH] Improve runtime error when indexing a non-indexable value The error for indexing a non-indexable value exposed the internal Go type name, e.g. `RUNTIME ERROR: Value non indexable: *jsonnet.valueNull`. Use the jsonnet type name instead and explain which types can be indexed, e.g. `Could not index a value of type "null" (only objects, arrays and strings can be indexed)`. Fixes #258 --- interpreter.go | 2 +- jsonnet_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/interpreter.go b/interpreter.go index 26df98a2e..42f05e109 100644 --- a/interpreter.go +++ b/interpreter.go @@ -505,7 +505,7 @@ func (i *interpreter) rawevaluate(a ast.Node, tc tailCallStatus) (value, error) return target.index(i, int(indexInt.value)) } - return nil, i.Error(fmt.Sprintf("Value non indexable: %v", reflect.TypeOf(targetValue))) + return nil, i.Error(fmt.Sprintf("Could not index a value of type %q (only objects, arrays and strings can be indexed)", targetValue.getType().name)) case *ast.Import: codePath := node.Loc().FileName diff --git a/jsonnet_test.go b/jsonnet_test.go index 4a864376f..48ab2dadb 100644 --- a/jsonnet_test.go +++ b/jsonnet_test.go @@ -350,3 +350,32 @@ func TestSetTraceOut(t *testing.T) { t.Errorf("Expected %q, but got %q", expected, actual) } } + +func TestIndexNonIndexableErrorMessage(t *testing.T) { + testCases := []struct { + name string + input string + typeName string + }{ + {name: "null", input: `null[42]`, typeName: "null"}, + {name: "number", input: `(42)[0]`, typeName: "number"}, + {name: "boolean", input: `true[0]`, typeName: "boolean"}, + {name: "function", input: `(function() 1)[0]`, typeName: "function"}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + vm := MakeVM() + _, err := vm.EvaluateAnonymousSnippet("test.jsonnet", tc.input) + if err == nil { + t.Fatalf("expected error, got nil") + } + if !strings.Contains(err.Error(), tc.typeName) { + t.Errorf("error %q should mention the jsonnet type %q", err.Error(), tc.typeName) + } + if strings.Contains(err.Error(), "jsonnet.value") { + t.Errorf("error %q should not leak internal Go type names", err.Error()) + } + }) + } +}