Component(s)
router
Component version
github.com/wundergraph/cosmo/router local build based on 5b323e7090c6
wgc version
N/A (not involved in the reproduction; router loads execution config from file)
controlplane version
N/A / local execution config
router version
dev (local build based on 5b323e7090c6)
What happened?
If a gRPC datasource schema contains a recursive input object, the router crashes with fatal error: stack overflow while handling a GraphQL request.
This appears to happen during gRPC execution-plan construction, before any upstream/plugin call is executed.
If possible, please create a PR with a failing test to illustrate the issue clearly.
Otherwise, please attach a minimum reproduction through a GitHub repository that includes
essential information such as the relevant subgraph SDLs.
Please also make sure that the instructions for the reproduction are clear, tested, and fully accurate.
Description
A recursive input shape like this is enough to reproduce the problem:
scalar JSON
type Mutation {
updateRule(input: UpdateRuleInput!): Rule!
}
type Rule {
id: ID!
}
input UpdateRuleInput {
id: ID!
conditions: ConditionsInput
}
input ConditionsInput {
and: [ConditionsInput!]
or: [ConditionsInput!]
key: String
value: JSON
}
The router loads the execution config successfully and starts normally. But as soon as a request hits the recursive input type, the process exits with stack overflow.
The stack trace repeatedly alternates between:
grpc_datasource.(*rpcPlanVisitor).buildMessageField
grpc_datasource.(*rpcPlanVisitor).buildMessageFromNode
From local debugging, the recursion happens in:
pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go:378
pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go:417
There does not seem to be a recursion guard / visited-type cache for recursive input object expansion.
Steps to Reproduce
- Start the router with a local execution config that includes a gRPC datasource and a recursive input object like
ConditionsInput above.
- Send a mutation such as:
{
"query": "mutation UpdateRule($input: UpdateRuleInput!) { updateRule(input: $input) { id } }",
"variables": {
"input": {
"id": "r1",
"conditions": null
}
}
}
- Observe that the router process exits instead of returning an error or forwarding the request.
Expected Result
The router should support valid recursive input objects, or at minimum reject them gracefully during config/planning with a normal error.
It should not crash the process.
Actual Result
The router process exits with:
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
The stack repeatedly shows buildMessageField -> buildMessageFromNode -> buildMessageField -> ... in grpc_datasource/execution_plan_visitor.go.
Environment information
Environment
OS: macOS (Apple Silicon)
Package Manager: Go modules
Compiler(if manually compiled): go1.23.0
Router configuration
listen_addr: "127.0.0.1:18080"
dev_mode: true
plugins:
enabled: false
execution_config:
file:
path: "./router.execution.config.json"
watch: true
Router execution config
{
"kind": "GRAPHQL",
"customGraphql": {
"grpc": {
"mapping": {
"service": "RpcService"
},
"protoSchema": "message UpdateRuleInput { string id = 1; ConditionsInput conditions = 2; } message ConditionsInput { repeated ConditionsInput and = 1; repeated ConditionsInput or = 2; google.protobuf.StringValue key = 3; google.protobuf.StringValue value = 4; }"
}
}
}
Log output
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
...
github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/grpc_datasource.(*rpcPlanVisitor).buildMessageField
...
github.com/wundergraph/graphql-go-tools/v2/pkg/engine/datasource/grpc_datasource.(*rpcPlanVisitor).buildMessageFromNode
Additional context
This was reproduced locally with plugins disabled, which suggests the crash happens before any plugin/upstream execution and is isolated to router plan construction for gRPC datasources.
Component(s)
router
Component version
github.com/wundergraph/cosmo/routerlocal build based on5b323e7090c6wgc version
N/A (not involved in the reproduction; router loads execution config from file)
controlplane version
N/A / local execution config
router version
dev (local build based on
5b323e7090c6)What happened?
If a gRPC datasource schema contains a recursive input object, the router crashes with
fatal error: stack overflowwhile handling a GraphQL request.This appears to happen during gRPC execution-plan construction, before any upstream/plugin call is executed.
If possible, please create a PR with a failing test to illustrate the issue clearly.
Otherwise, please attach a minimum reproduction through a GitHub repository that includes
essential information such as the relevant subgraph SDLs.
Please also make sure that the instructions for the reproduction are clear, tested, and fully accurate.
Description
A recursive input shape like this is enough to reproduce the problem:
The router loads the execution config successfully and starts normally. But as soon as a request hits the recursive input type, the process exits with
stack overflow.The stack trace repeatedly alternates between:
grpc_datasource.(*rpcPlanVisitor).buildMessageFieldgrpc_datasource.(*rpcPlanVisitor).buildMessageFromNodeFrom local debugging, the recursion happens in:
pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go:378pkg/engine/datasource/grpc_datasource/execution_plan_visitor.go:417There does not seem to be a recursion guard / visited-type cache for recursive input object expansion.
Steps to Reproduce
ConditionsInputabove.{ "query": "mutation UpdateRule($input: UpdateRuleInput!) { updateRule(input: $input) { id } }", "variables": { "input": { "id": "r1", "conditions": null } } }Expected Result
The router should support valid recursive input objects, or at minimum reject them gracefully during config/planning with a normal error.
It should not crash the process.
Actual Result
The router process exits with:
The stack repeatedly shows
buildMessageField -> buildMessageFromNode -> buildMessageField -> ...ingrpc_datasource/execution_plan_visitor.go.Environment information
Environment
OS: macOS (Apple Silicon)
Package Manager: Go modules
Compiler(if manually compiled): go1.23.0
Router configuration
Router execution config
{ "kind": "GRAPHQL", "customGraphql": { "grpc": { "mapping": { "service": "RpcService" }, "protoSchema": "message UpdateRuleInput { string id = 1; ConditionsInput conditions = 2; } message ConditionsInput { repeated ConditionsInput and = 1; repeated ConditionsInput or = 2; google.protobuf.StringValue key = 3; google.protobuf.StringValue value = 4; }" } } }Log output
Additional context
This was reproduced locally with plugins disabled, which suggests the crash happens before any plugin/upstream execution and is isolated to router plan construction for gRPC datasources.