Skip to content

[Fusion] ForwardedVariables are not passed to all resolvers #8201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Bukk94 opened this issue Mar 31, 2025 · 0 comments
Open

[Fusion] ForwardedVariables are not passed to all resolvers #8201

Bukk94 opened this issue Mar 31, 2025 · 0 comments

Comments

@Bukk94
Copy link

Bukk94 commented Mar 31, 2025

Product

Hot Chocolate

Version

15.1.1

Link to minimal reproduction

https://www.dropbox.com/scl/fi/av26h4zc1x27kyejsoapc/GqlGatewayPoC.rar?rlkey=03945jt4rgwgfeqcgnbn4pxpr&st=cc7ozct4&dl=0

Steps to reproduce

Create two GQL servers, both containing the same method, returning their own results. For example:

  • ServiceA with method Suggest, returning ProcessingResult with values a
  • ServiceB with method Suggest, returning ProcessingResult with values b

Then create Fusion gateway, produce FGP file, merging those two services into supergraph on the gateway.
dotnet fusion compose -p .\Gateway\gateway.fgp -s .\out\serviceA.fsp
dotnet fusion compose -p .\Gateway\gateway.fgp -s .\out\serviceB.fsp

What is expected?

Gateway will stitch two services into a single call, distributing the queries in parallel to their respective resolvers, passing all parameters down the stream.

What is actually happening?

fusion.graphql correctly contains stitched method suggest, returning merged ProcessingResult

type Query {
  suggest(limit: Int! = 3 query: String!): ProcessingResult!
    @cost(weight: "10")
    @variable(subgraph: "serviceA", name: "query", argument: "query")
    @variable(subgraph: "serviceA", name: "limit", argument: "limit")
    @resolver(subgraph: "serviceA", select: "{ suggest(query: $query, limit: $limit) }", arguments: [ { name: "query", type: "String!" }, { name: "limit", type: "Int!" } ])
    @variable(subgraph: "serviceB", name: "query", argument: "query")
    @variable(subgraph: "serviceB", name: "limit", argument: "limit")
    @resolver(subgraph: "serviceB", select: "{ suggest(query: $query, limit: $limit) }", arguments: [ { name: "query", type: "String!" }, { name: "limit", type: "Int!" } ])
}

type ProcessingResult {
  a: String!
    @source(subgraph: "serviceA")
  b: String!
    @source(subgraph: "serviceB")
}

When called with inlined arguments, it works correctly, getting the results. The problem happens when you use query variables:

query Suggest($limit: Int, $query: String!) {
    suggest(limit: $limit, query: $query) {
             a
             b
	}
}

This will produce parallel query to both services, but providing variables only to the first service. Second service is completely missing forwardedVariables and crashing on missing input:

"type": "Parallel",
"nodes": [
	{
		"type": "Resolve",
		"subgraph": "serviceA",
		"document": "query Suggest_1($query: String!, $limit: Int!) { suggest(query: $query, limit: $limit) { a } }",
		"selectionSetId": 0,
		"forwardedVariables": [
			{
				"variable": "query"
			},
			{
				"variable": "limit"
			}
		]
	},
	{
		"type": "Resolve",
		"subgraph": "serviceB",
		"document": "query Suggest_2 { suggest(limit: $limit, query: $query) { b } }",
		"selectionSetId": 0
	}
]

Image

Relevant log output

Response, including the query plan:

{
    "errors": [
        {
            "message": "The following variables were not declared: limit, query.",
            "locations": [
                {
                    "line": 1,
                    "column": 1
                }
            ],
            "extensions": {
                "specifiedBy": "https://spec.graphql.org/October2021/#sec-All-Variable-Uses-Defined"
            }
        },
        {
            "message": "Cannot return null for non-nullable field.",
            "locations": [
                {
                    "line": 2,
                    "column": 5
                }
            ],
            "path": [
                "suggest"
            ],
            "extensions": {
                "code": "HC0018"
            }
        },
        {
            "message": "Cannot return null for non-nullable field.",
            "locations": [
                {
                    "line": 4,
                    "column": 9
                }
            ],
            "path": [
                "suggest",
                "b"
            ],
            "extensions": {
                "code": "HC0018"
            }
        }
    ],
    "data": null,
    "extensions": {
        "queryPlan": {
            "document": "query Suggest($limit: Int, $query: String!) { suggest(limit: $limit, query: $query) { a b } }",
            "operation": "Suggest",
            "rootNode": {
                "type": "Sequence",
                "nodes": [
                    {
                        "type": "Parallel",
                        "nodes": [
                            {
                                "type": "Resolve",
                                "subgraph": "serviceA",
                                "document": "query Suggest_1($limit: Int!, $query: String!) { suggest(limit: $limit, query: $query) { a } }",
                                "selectionSetId": 0,
                                "forwardedVariables": [
                                    {
                                        "variable": "limit"
                                    },
                                    {
                                        "variable": "query"
                                    }
                                ]
                            },
                            {
                                "type": "Resolve",
                                "subgraph": "serviceB",
                                "document": "query Suggest_2 { suggest(limit: $limit, query: $query) { b } }",
                                "selectionSetId": 0
                            }
                        ]
                    },
                    {
                        "type": "Compose",
                        "selectionSetIds": [
                            0
                        ]
                    }
                ]
            }
        },
        "queryPlanHash": "2169A85A87BD51CC34F4BC44E35BE44883046E2A"
    }
}

Additional context

No response

@Bukk94 Bukk94 changed the title ForwardedVariables are not passed to all resolvers [Fusion] ForwardedVariables are not passed to all resolvers Mar 31, 2025
@michaelstaib michaelstaib added this to the HC-15.2.0 milestone Mar 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants