STET

agent_patch

runs/2026-02-28__13-38-10__gpt-5-3-codex/flux-pr-1155/flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/agent-logs/agent.patch

20343 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/configuration.go b/app/v2/pkg/engine/datasource/graphql_datasource/configuration.go
index f876776..fe219cb 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/configuration.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/configuration.go
@@ -96,7 +96,7 @@ func (c *Configuration) FederationConfiguration() *FederationConfiguration {
 }
 
 func (c *Configuration) IsGRPC() bool {
-	return c.grpc != nil
+	return c.grpc != nil && !c.grpc.Disabled
 }
 
 type SingleTypeField struct {
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
index 1d45769..bbdf117 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource.go
@@ -317,7 +317,8 @@ func (p *Planner[T]) createInputForQuery() (input, operation []byte) {
 }
 
 func (p *Planner[T]) ConfigureFetch() resolve.FetchConfiguration {
-	if p.config.fetch == nil && p.config.grpc == nil {
+	grpcEnabled := p.config.grpc != nil && !p.config.grpc.Disabled
+	if p.config.fetch == nil && !grpcEnabled {
 		p.stopWithError(errors.WithStack(errors.New("ConfigureFetch: fetch and grpc configuration is empty")))
 		return resolve.FetchConfiguration{}
 	}
@@ -353,8 +354,22 @@ func (p *Planner[T]) ConfigureFetch() resolve.FetchConfiguration {
 
 	dataSource = &Source{httpClient: p.fetchClient}
 
-	if p.config.grpc != nil {
+	if grpcEnabled {
 		var err error
+		grpcClient := p.grpcClient
+		if p.config.grpc.Client != nil {
+			grpcClient = p.config.grpc.Client
+		} else if p.config.grpc.ClientFactory != nil {
+			grpcClient, err = p.config.grpc.ClientFactory()
+			if err != nil {
+				p.stopWithError(errors.WithStack(fmt.Errorf("failed to create gRPC client from factory: %w", err)))
+				return resolve.FetchConfiguration{}
+			}
+		}
+		if grpcClient == nil {
+			p.stopWithError(errors.WithStack(errors.New("failed to create gRPC datasource: grpc client is required")))
+			return resolve.FetchConfiguration{}
+		}
 
 		opDocument, opReport := astparser.ParseGraphqlDocumentBytes(operation)
 		if opReport.HasErrors() {
@@ -362,7 +377,7 @@ func (p *Planner[T]) ConfigureFetch() resolve.FetchConfiguration {
 			return resolve.FetchConfiguration{}
 		}
 
-		dataSource, err = grpcdatasource.NewDataSource(p.grpcClient, grpcdatasource.DataSourceConfig{
+		dataSource, err = grpcdatasource.NewDataSource(grpcClient, grpcdatasource.DataSourceConfig{
 			Operation:  &opDocument,
 			Definition: p.config.schemaConfiguration.upstreamSchemaAst,
 			Mapping:    p.config.grpc.Mapping,
@@ -1736,10 +1751,6 @@ func NewFactoryGRPC(executionContext context.Context, grpcClient grpc.ClientConn
 		return nil, fmt.Errorf("execution context is required")
 	}
 
-	if grpcClient == nil {
-		return nil, fmt.Errorf("grpc client is required")
-	}
-
 	return &Factory[Configuration]{
 		executionContext: executionContext,
 		grpcClient:       grpcClient,
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_test.go b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_test.go
index eff6a10..fbd4c0d 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_test.go
+++ b/app/v2/pkg/engine/datasource/graphql_datasource/graphql_datasource_test.go
@@ -23,6 +23,7 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
+	grpcdatasource "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/grpc_datasource"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/httpclient"
 	. "github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasourcetesting"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/plan"
@@ -65,6 +66,17 @@ func mustDataSourceConfigurationWithHttpClient(t *testing.T, id string, metadata
 	return dsCfg
 }
 
+func TestConfiguration_IsGRPC_Disabled(t *testing.T) {
+	cfg := mustCustomConfiguration(t, ConfigurationInput{
+		SchemaConfiguration: mustSchema(t, nil, "type Query { hello: String }"),
+		GRPC: &grpcdatasource.GRPCConfiguration{
+			Disabled: true,
+		},
+	})
+
+	require.False(t, cfg.IsGRPC())
+}
+
 func TestGraphQLDataSource(t *testing.T) {
 	t.Run("query with double nested fragments with fragment on union", func(t *testing.T) {
 		definition := `
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go b/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go
index ed8b887..166c9f6 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/compiler.go
@@ -400,16 +400,42 @@ func (p *RPCCompiler) buildProtoMessage(inputMessage Message, rpcMessage *RPCMes
 			// Get a mutable reference to the list field
 			list := message.Mutable(fd.ByName(protoref.Name(field.Name))).List()
 
-			// Extract the array elements from the JSON data
-			elements := data.Get(rpcField.JSONPath).Array()
+			// Extract the array elements from the JSON data. If a scalar is provided for a list field,
+			// treat it as a single-item list to match GraphQL list coercion behavior.
+			elements := p.listInputElements(data.Get(rpcField.JSONPath))
 			if len(elements) == 0 {
 				continue
 			}
 
 			// Process each element and append to the list
 			for _, element := range elements {
-				fieldMsg := p.buildProtoMessage(p.doc.Messages[field.MessageRef], rpcField.Message, element)
-				list.Append(protoref.ValueOfMessage(fieldMsg))
+				if field.MessageRef >= 0 {
+					fieldMsg := p.buildProtoMessage(p.doc.Messages[field.MessageRef], rpcField.Message, element)
+					if fieldMsg == nil {
+						continue
+					}
+
+					list.Append(protoref.ValueOfMessage(fieldMsg))
+					continue
+				}
+
+				if field.Type == DataTypeEnum {
+					enum, ok := p.doc.EnumByName(rpcField.EnumName)
+					if !ok {
+						p.report.AddInternalError(fmt.Errorf("enum %s not found in document", rpcField.EnumName))
+						continue
+					}
+
+					enumNumber, ok := p.resolveEnumNumber(enum, element.String())
+					if !ok {
+						continue
+					}
+
+					list.Append(protoref.ValueOfEnum(protoref.EnumNumber(enumNumber)))
+					continue
+				}
+
+				list.Append(p.setValueForKind(field.Type, element))
 			}
 
 			continue
@@ -430,17 +456,16 @@ func (p *RPCCompiler) buildProtoMessage(inputMessage Message, rpcMessage *RPCMes
 				continue
 			}
 
-			for _, enumValue := range enum.Values {
-				if enumValue.GraphqlValue == data.Get(rpcField.JSONPath).String() {
-					message.Set(
-						fd.ByName(protoref.Name(field.Name)),
-						protoref.ValueOfEnum(protoref.EnumNumber(enumValue.Number)),
-					)
-
-					break
-				}
+			enumNumber, ok := p.resolveEnumNumber(enum, data.Get(rpcField.JSONPath).String())
+			if !ok {
+				continue
 			}
 
+			message.Set(
+				fd.ByName(protoref.Name(field.Name)),
+				protoref.ValueOfEnum(protoref.EnumNumber(enumNumber)),
+			)
+
 			continue
 		}
 
@@ -463,20 +488,44 @@ func (p *RPCCompiler) setValueForKind(kind DataType, data gjson.Result) protoref
 	case DataTypeInt64:
 		return protoref.ValueOfInt64(data.Int())
 	case DataTypeUint32:
-		return protoref.ValueOfUint32(uint32(data.Int()))
+		return protoref.ValueOfUint32(uint32(data.Uint()))
 	case DataTypeUint64:
-		return protoref.ValueOfUint64(uint64(data.Int()))
+		return protoref.ValueOfUint64(data.Uint())
 	case DataTypeFloat:
 		return protoref.ValueOfFloat32(float32(data.Float()))
 	case DataTypeDouble:
 		return protoref.ValueOfFloat64(data.Float())
 	case DataTypeBool:
 		return protoref.ValueOfBool(data.Bool())
+	case DataTypeBytes:
+		return protoref.ValueOfBytes([]byte(data.String()))
 	}
 
 	return protoref.Value{}
 }
 
+func (p *RPCCompiler) listInputElements(value gjson.Result) []gjson.Result {
+	if !value.Exists() || value.Type == gjson.Null {
+		return nil
+	}
+
+	if value.IsArray() {
+		return value.Array()
+	}
+
+	return []gjson.Result{value}
+}
+
+func (p *RPCCompiler) resolveEnumNumber(enum Enum, graphqlValue string) (int32, bool) {
+	for _, enumValue := range enum.Values {
+		if enumValue.GraphqlValue == graphqlValue || enumValue.Name == graphqlValue {
+			return enumValue.Number, true
+		}
+	}
+
+	return 0, false
+}
+
 // parseEnum extracts information from a protobuf enum descriptor.
 func (p *RPCCompiler) parseEnum(e protoref.EnumDescriptor, mapping *GRPCMapping) Enum {
 	var enumValueMappings []EnumValueMapping
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go b/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go
index 5e098c3..ecad543 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/compiler_test.go
@@ -6,6 +6,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/tidwall/gjson"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/grpctest"
+	protoref "google.golang.org/protobuf/reflect/protoreflect"
 )
 
 // Complete valid protobuf definition with service and message definitions
@@ -291,3 +292,56 @@ func TestBuildProtoMessage(t *testing.T) {
 	require.Equal(t, 1, len(invocations))
 
 }
+
+func TestBuildProtoMessage_RepeatedScalarWithScalarInput(t *testing.T) {
+	schema := `
+syntax = "proto3";
+package test.v1;
+
+service TestService {
+  rpc QueryTags(QueryTagsRequest) returns (QueryTagsResponse) {}
+}
+
+message QueryTagsRequest {
+  repeated string tags = 1;
+}
+
+message QueryTagsResponse {}
+`
+	compiler, err := NewProtoCompiler(schema, nil)
+	require.NoError(t, err)
+
+	executionPlan := &RPCExecutionPlan{
+		Calls: []RPCCall{
+			{
+				MethodName: "QueryTags",
+				Request: RPCMessage{
+					Name: "QueryTagsRequest",
+					Fields: []RPCField{
+						{
+							Name:     "kinds",
+							TypeName: string(DataTypeString),
+							JSONPath: "tags",
+							Repeated: true,
+						},
+					},
+				},
+				Response: RPCMessage{Name: "QueryTagsResponse"},
+			},
+		},
+	}
+
+	executionPlan.Calls[0].Request.Fields[0].Name = "tags"
+
+	variables := []byte(`{"variables":{"tags":"single"}}`)
+	invocations, err := compiler.Compile(executionPlan, gjson.ParseBytes(variables).Get("variables"))
+	require.NoError(t, err)
+	require.Len(t, invocations, 1)
+
+	fd := invocations[0].Input.Descriptor().Fields().ByName(protoref.Name("tags"))
+	require.NotNil(t, fd)
+
+	list := invocations[0].Input.Get(fd).List()
+	require.Equal(t, 1, list.Len())
+	require.Equal(t, "single", list.Get(0).String())
+}
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/configuration.go b/app/v2/pkg/engine/datasource/grpc_datasource/configuration.go
index 4dbd48b..ead8fe8 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/configuration.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/configuration.go
@@ -1,5 +1,7 @@
 package grpcdatasource
 
+import "google.golang.org/grpc"
+
 type (
 	// RPCConfigMap is a map of RPC names to RPC configurations
 	RPCConfigMap map[string]RPCConfig
@@ -32,6 +34,13 @@ type EnumValueMapping struct {
 type GRPCConfiguration struct {
 	Mapping  *GRPCMapping
 	Compiler *RPCCompiler
+
+	// Disabled allows switching off gRPC execution while keeping the config attached.
+	Disabled bool
+	// Client allows overriding the default factory-level gRPC client for this datasource.
+	Client grpc.ClientConnInterface
+	// ClientFactory allows creating a datasource-specific client dynamically.
+	ClientFactory func() (grpc.ClientConnInterface, error)
 }
 
 // RPCConfig defines the configuration for a specific RPC operation
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource.go b/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource.go
index 940d501..2df4490 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource.go
@@ -17,6 +17,7 @@ import (
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/httpclient"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/engine/resolve"
 	"google.golang.org/grpc"
+	"google.golang.org/grpc/status"
 	protoref "google.golang.org/protobuf/reflect/protoreflect"
 )
 
@@ -123,7 +124,11 @@ func (d *DataSource) LoadWithFiles(ctx context.Context, input []byte, files []*h
 
 func (d *DataSource) marshalResponseJSON(arena *astjson.Arena, message *RPCMessage, data protoref.Message) (*astjson.Value, error) {
 	if message == nil {
-		return nil, nil
+		return arena.NewNull(), nil
+	}
+
+	if !data.IsValid() {
+		return arena.NewNull(), nil
 	}
 
 	root := arena.NewObject()
@@ -161,20 +166,35 @@ func (d *DataSource) marshalResponseJSON(arena *astjson.Arena, message *RPCMessa
 			arr := arena.NewArray()
 			root.Set(field.JSONPath, arr)
 			list := data.Get(fd).List()
+			if !list.IsValid() {
+				root.Set(field.JSONPath, arena.NewNull())
+				continue
+			}
+
 			for i := 0; i < list.Len(); i++ {
-				message := list.Get(i).Message()
-				value, err := d.marshalResponseJSON(arena, field.Message, message)
-				if err != nil {
-					return nil, err
+				item := list.Get(i)
+				if field.Message != nil || fd.Kind() == protoref.MessageKind {
+					value, err := d.marshalResponseJSON(arena, field.Message, item.Message())
+					if err != nil {
+						return nil, err
+					}
+
+					arr.SetArrayItem(i, value)
+					continue
 				}
 
-				arr.SetArrayItem(i, value)
+				arr.SetArrayItem(i, d.jsonValueForKind(arena, data, fd, item))
 			}
 
 			continue
 		}
 
 		if fd.Kind() == protoref.MessageKind {
+			if !data.Has(fd) {
+				root.Set(field.JSONPath, arena.NewNull())
+				continue
+			}
+
 			msg := data.Get(fd).Message()
 			value, err := d.marshalResponseJSON(arena, field.Message, msg)
 			if err != nil {
@@ -193,47 +213,47 @@ func (d *DataSource) marshalResponseJSON(arena *astjson.Arena, message *RPCMessa
 			continue
 		}
 
-		d.setJSONValue(arena, root, field.JSONPath, data, fd)
+		root.Set(field.JSONPath, d.jsonValueForKind(arena, data, fd, data.Get(fd)))
 	}
 
 	return root, nil
 }
 
-func (d *DataSource) setJSONValue(arena *astjson.Arena, root *astjson.Value, name string, data protoref.Message, fd protoref.FieldDescriptor) {
+func (d *DataSource) jsonValueForKind(arena *astjson.Arena, data protoref.Message, fd protoref.FieldDescriptor, value protoref.Value) *astjson.Value {
 	switch fd.Kind() {
 	case protoref.BoolKind:
-		boolValue := data.Get(fd).Bool()
+		boolValue := value.Bool()
 		if boolValue {
-			root.Set(name, arena.NewTrue())
+			return arena.NewTrue()
 		} else {
-			root.Set(name, arena.NewFalse())
+			return arena.NewFalse()
 		}
 	case protoref.StringKind:
-		root.Set(name, arena.NewString(data.Get(fd).String()))
+		return arena.NewString(value.String())
 	case protoref.Int32Kind, protoref.Int64Kind:
-		root.Set(name, arena.NewNumberInt(int(data.Get(fd).Int())))
+		return arena.NewNumberInt(int(value.Int()))
 	case protoref.Uint32Kind, protoref.Uint64Kind:
-		root.Set(name, arena.NewNumberString(fmt.Sprintf("%d", data.Get(fd).Uint())))
+		return arena.NewNumberString(fmt.Sprintf("%d", value.Uint()))
 	case protoref.FloatKind, protoref.DoubleKind:
-		root.Set(name, arena.NewNumberFloat64(data.Get(fd).Float()))
+		return arena.NewNumberFloat64(value.Float())
 	case protoref.BytesKind:
-		root.Set(name, arena.NewStringBytes(data.Get(fd).Bytes()))
+		return arena.NewStringBytes(value.Bytes())
 	case protoref.EnumKind:
 		enumDesc := fd.Enum()
-		enumValueDesc := enumDesc.Values().ByNumber(data.Get(fd).Enum())
+		enumValueDesc := enumDesc.Values().ByNumber(value.Enum())
 		if enumValueDesc == nil {
-			root.Set(name, arena.NewNull())
-			return
+			return arena.NewNull()
 		}
 
 		graphqlValue, ok := d.mapping.ResolveEnumValue(string(enumDesc.Name()), string(enumValueDesc.Name()))
 		if !ok {
-			root.Set(name, arena.NewNull())
-			return
+			return arena.NewNull()
 		}
 
-		root.Set(name, arena.NewString(graphqlValue))
+		return arena.NewString(graphqlValue)
 	}
+
+	return arena.NewNull()
 }
 
 func writeErrorBytes(err error) []byte {
@@ -244,6 +264,14 @@ func writeErrorBytes(err error) []byte {
 
 	errorItem := a.NewObject()
 	errorItem.Set("message", a.NewString(err.Error()))
+
+	if st, ok := status.FromError(err); ok {
+		extensions := a.NewObject()
+		extensions.Set("grpcStatusCode", a.NewNumberInt(int(st.Code())))
+		extensions.Set("grpcStatusName", a.NewString(st.Code().String()))
+		errorItem.Set("extensions", extensions)
+	}
+
 	errorArray.SetArrayItem(0, errorItem)
 
 	return errorRoot.MarshalTo(nil)
diff --git a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go b/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go
index a14f5a1..0d62661 100644
--- a/tmp/agent-patch-flux-pr-1155.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go
+++ b/app/v2/pkg/engine/datasource/grpc_datasource/grpc_datasource_test.go
@@ -425,6 +425,8 @@ func Test_DataSource_Load_WithGrpcError(t *testing.T) {
 
 	// Verify the error message
 	require.Contains(t, response.Errors[0].Message, "user not found: error-user")
+	require.Contains(t, responseJson, `"grpcStatusCode":5`)
+	require.Contains(t, responseJson, `"grpcStatusName":"NotFound"`)
 }
 
 func TestMarshalResponseJSON(t *testing.T) {
@@ -493,6 +495,62 @@ func TestMarshalResponseJSON(t *testing.T) {
 	require.Equal(t, `{"_entities":[{"__typename":"Product","id":"123","name_different":"test","price_different":123.45}]}`, responseJSON.String())
 }
 
+func TestMarshalResponseJSON_RepeatedScalar(t *testing.T) {
+	schema := `
+syntax = "proto3";
+package test.v1;
+
+service TestService {
+  rpc QueryTags(QueryTagsRequest) returns (QueryTagsResponse) {}
+}
+
+message QueryTagsRequest {}
+message QueryTagsResponse {
+  repeated string tags = 1;
+  repeated int32 counts = 2;
+}
+`
+	compiler, err := NewProtoCompiler(schema, nil)
+	require.NoError(t, err)
+
+	response := RPCMessage{
+		Name: "QueryTagsResponse",
+		Fields: []RPCField{
+			{
+				Name:     "tags",
+				TypeName: string(DataTypeString),
+				JSONPath: "tags",
+				Repeated: true,
+			},
+			{
+				Name:     "counts",
+				TypeName: string(DataTypeInt32),
+				JSONPath: "counts",
+				Repeated: true,
+			},
+		},
+	}
+
+	responseMessageDesc := compiler.doc.MessageByName("QueryTagsResponse").Desc
+	responseMessage := dynamicpb.NewMessage(responseMessageDesc)
+
+	tagsField := responseMessageDesc.Fields().ByName("tags")
+	tagsList := responseMessage.Mutable(tagsField).List()
+	tagsList.Append(protoref.ValueOfString("one"))
+	tagsList.Append(protoref.ValueOfString("two"))
+
+	countsField := responseMessageDesc.Fields().ByName("counts")
+	countsList := responseMessage.Mutable(countsField).List()
+	countsList.Append(protoref.ValueOfInt32(1))
+	countsList.Append(protoref.ValueOfInt32(2))
+
+	ds := &DataSource{}
+	arena := astjson.Arena{}
+	responseJSON, err := ds.marshalResponseJSON(&arena, &response, responseMessage)
+	require.NoError(t, err)
+	require.Equal(t, `{"tags":["one","two"],"counts":[1,2]}`, responseJSON.String())
+}
+
 // TODO test interface types
 // Test_DataSource_Load_WithAnimalInterface tests the datasource with Animal interface types (Cat/Dog)
 // using a bufconn connection to the mock service