ChilliCream / ChilliCream/graphql-platform
`totalCount @include(if: $var)` on a connection is frozen by the first execution of the document
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 5.8k
- Forks
- 810
- Avg merge
- 15h 39m
- Merged PRs (30d)
- 98
Description
Product
Hot Chocolate
Version
16.6.6
Link to minimal reproduction
https://github.com/drebouta/graphql-platform-conditional-total-count-issue-repro
Steps to reproduce
dotnet run the app runs the same document twice, changing only the variable. It does that
twice over, each time with a fresh executor: run A starts with the variable false, run B starts with it true.
query Items($withTotalCount: Boolean!) {
items(first: 10) {
totalCount @include(if: $withTotalCount)
nodes
}
}
- Execute with
{ "withTotalCount": false } - Execute the same document with
{ "withTotalCount": true } - On a fresh executor, execute the same two requests in the opposite order
What is expected?
totalCount should return the value conditionaly upon requesting.
What is actually happening?
If the first execution @include evaluates to false, every execution afterwards fails with {"errors":[{"message":"Cannot return null for non-nullable field.","path":["items","totalCount"],"extensions":{"code":"HC0018"}}],"data":null}.
The document resolved @include to is reused for the lifetime of the compiled operation.
The resolver is handed ConnectionFlags = Nodes and PagingArguments.IncludeTotalCount = false,
so the page carries no count, while the response still shapes the totalCount: Int! field.
Run B - the same requests in the opposite order - works throughout, and there the count is
computed even for the request that did not ask for it. Only the order differs between the runs.
Relevant log output
dotnet run
A: first execution does not ask for totalCount
withTotalCount: False
resolver: Nodes | IncludeTotalCount: False
{"data":{"items":{"nodes":["a","b","c"]}}}
withTotalCount: True
resolver: Nodes | IncludeTotalCount: False
{"errors":[{"message":"Cannot return null for non-nullable field.","path":["items","totalCount"],"extensions":{"code":"HC0018"}}],"data":null}
B: first execution asks for totalCount
withTotalCount: True
resolver: Nodes, TotalCount | IncludeTotalCount: True
{"data":{"items":{"totalCount":3,"nodes":["a","b","c"]}}}
withTotalCount: False
resolver: Nodes, TotalCount | IncludeTotalCount: True
{"data":{"items":{"nodes":["a","b","c"]}}}
withTotalCount: True
resolver: Nodes, TotalCount | IncludeTotalCount: True
{"data":{"items":{"totalCount":3,"nodes":["a","b","c"]}}}
Additional context
- Reproduces on 16.6.6
- The repro is a source-generated
[QueryType]resolver with aPagingArgumentsparameter and
ModifyPagingOptions(o => o.IncludeTotalCount = true), over an in-memory list; the
ConnectionFlagsparameter is there only to show the value the resolver receives. - Workaround: select
totalCountunconditionally, or move the conditional variant into its own
document. - Caught in production: Application restart together with first query having
include: flaseresulted in this issue, causing a major outage, since a very frequently used query was affected.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the linked minimal reproduction with its source-generated [QueryType] resolver, PagingArguments, and ModifyPagingOptions configuration. Trace how the compiled operation reuses the @include result and how ConnectionFlags and IncludeTotalCount are produced across repeated executions. Done means the same document honors the variable on every execution regardless of which value runs first, with regression coverage for both orders.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, graphql
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100