-
-
Notifications
You must be signed in to change notification settings - Fork 786
Description
Product
Strawberry Shake
Version
15.0.3
Link to minimal reproduction
https://github.com/samyonr/StrawberryShake.OrderOfInlineFragment.Bug
Steps to reproduce
- Clone or download the attached repo.
cd StrawberryShake.OrderOfInlineFragment.Bug.Tests
dotnet test
- Observe that
FragmentOrderBug_PartialFragment_Failing
test fails, while the others pass.
Run the tests and note that:
FragmentOrderBug_FullFragment_Working()
→ PASS. Because the Bird fragment is requested for both people and shelters.FragmentOrderBug_FullFragment_ExplicitQuery_Working()
→ PASS. We manually post the full query to /graphql and the JSON contains Bird data.FragmentOrderBug_PartialFragment_Failing()
→ FAIL. Strawberry Shake’s typed result incorrectly omits Bird fields or treats it as null. The server response definitely includes them.FragmentOrderBug_PartialFragment_ExplicitQuery_Working()
→ PASS. Manually posting the partial query returns Bird data.
What is expected?
Expected
When we run NotWorkingQuery
, the first shelter’s pet (a Bird) should appear with wingSpan=42
. The server’s raw JSON response includes it, so the Strawberry Shake client should include it as well.
Actual
.Data
is null, and .Error
is Value cannot be null.
What is actually happening?
Actual
.Data
is null, and .Error
is Value cannot be null.
For the auto-generated schema below (generated with dotnet graphql init http://localhost:5058/graphql -n StrawBerryShakeClient
):
schema {
query: Query
}
interface IPet {
id: Int!
}
type Query {
people: [Person!]!
shelters: [Shelter!]!
}
type Dog implements IPet {
id: Int!
breed: String!
}
type Cat implements IPet {
id: Int!
furColor: String!
}
type Bird implements IPet {
id: Int!
wingSpan: Int!
}
type Shelter {
id: Int!
location: String!
pet: IPet
}
type Person {
id: Int!
name: String!
pet: IPet
}
We are running two queries:
query WorkingQuery {
people {
id
name
pet {
id
__typename
... on Bird {
wingSpan
}
... on Cat {
furColor
}
... on Dog {
breed
}
}
}
shelters {
id
location
pet {
id
__typename
... on Bird {
wingSpan
}
... on Cat {
furColor
}
... on Dog {
breed
}
}
}
}
and:
query NotWorkingQuery {
people {
id
name
pet {
id
__typename
... on Cat {
furColor
}
... on Dog {
breed
}
}
}
shelters {
id
location
pet {
id
__typename
... on Bird {
wingSpan
}
... on Cat {
furColor
}
... on Dog {
breed
}
}
}
}
The second query doesn't work for the Strawberry Shake client, but it does work when we send the query explicitly, without a client.
- The problem seems to arise specifically when the first object (
people
) omits one of the possible implementing types (e.g.Bird
), but the second object (shelters
) references it. If the second object requests the missing type, Strawberry Shake’s client fails. - If you reverse the order of fields in the query or ensure all fragments are used in both cases, it works fine.
- This bug has been observed in various versions of Strawberry Shake (e.g. ~13.x – 15.x).
Relevant log output
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v3.0.2+dd36e86129 (64-bit .NET 9.0.2)
[xUnit.net 00:00:03.09] Discovering: StrawberryShake.OrderOfInlineFragment.Bug.Tests
[xUnit.net 00:00:03.29] Discovered: StrawberryShake.OrderOfInlineFragment.Bug.Tests
[xUnit.net 00:00:03.54] Starting: StrawberryShake.OrderOfInlineFragment.Bug.Tests
[xUnit.net 00:00:08.79] StrawberryShake.OrderOfInlineFragment.Bug.Tests.Reproduction.FragmentOrderBug_PartialFragment_Failing [FAIL]
[xUnit.net 00:00:08.79] Assert.NotNull() Failure: Value is null
[xUnit.net 00:00:08.79] Stack Trace:
[xUnit.net 00:00:08.79] StrawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.OrderOfInlineFragment.Bug.Tests\Reproduction.cs(73,0): at StrawberryShake.OrderOfInlineFragment.Bug.Tests.Reproduction.FragmentOrderBug_PartialFragment_Failing()
[xUnit.net 00:00:08.79] --- End of stack trace from previous location ---
[xUnit.net 00:00:08.88] Finished: StrawberryShake.OrderOfInlineFragment.Bug.Tests
StrawberryShake.OrderOfInlineFragment.Bug.Tests test failed with 1 error(s) (10.7s)
StrawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.OrderOfInlineFragment.Bug.Tests\Reproduction.cs(73): error TESTERROR:
StrawberryShake.OrderOfInlineFragment.Bug.Tests.Reproduction.FragmentOrderBug_PartialFragment_Failing (5s 174ms): Error Message: Assert.NotNull() Failure: Value is null
Stack Trace:
at StrawberryShake.OrderOfInlineFragment.Bug.Tests.Reproduction.FragmentOrderBug_PartialFragment_Failing() in StrawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.O rderOfInlineFragment.Bug.Tests\Reproduction.cs:line 73
--- End of stack trace from previous location ---
Test summary: total: 4, failed: 1, succeeded: 3, skipped: 0, duration: 10.6s
Build failed with 1 error(s) in 15.8s
---
and when debugging:
System.ArgumentNullException: Value cannot be null.
at StrawberryShake.OrderOfInlineFragment.Bug.Tests.State.NotWorkingQueryResultFactory.MapINotWorkingQuery_Shelters_Pet(IIPetData data) in StrawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.OrderOfInlineFragment.Bug.Tests\obj\Debug\net9.0\berry\StrawBerryShakeClient.Client.cs:line 2630
at StrawberryShake.OrderOfInlineFragment.Bug.Tests.State.NotWorkingQueryResultFactory.MapNonNullableINotWorkingQuery_Shelters(ShelterData data) in StrawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.OrderOfInlineFragment.Bug.Tests\obj\Debug\net9.0\berry\StrawBerryShakeClient.Client.cs:line 2585
at StrawberryShake.OrderOfInlineFragment.Bug.Tests.State.NotWorkingQueryResultFactory.MapNonNullableINotWorkingQuery_SheltersNonNullableArray(IReadOnlyList`1 list) in trawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.OrderOfInlineFragment.Bug.Tests\obj\Debug\net9.0\berry\StrawBerryShakeClient.Client.cs:line 2574
at StrawberryShake.OrderOfInlineFragment.Bug.Tests.State.NotWorkingQueryResultFactory.Create(IOperationResultDataInfo dataInfo, IEntityStoreSnapshot snapshot) in StrawberryShake.OrderOfInlineFragment.Bug\StrawberryShake.OrderOfInlineFragment.Bug.Tests\obj\Debug\net9.0\berry\StrawBerryShakeClient.Client.cs:line 2484
at StrawberryShake.OperationResultBuilder`1.Build(Response`1 response)
Additional context
Strawberry Shake Bug: Order of Inline Fragments Causes Missing Data
A bug in Strawberry Shake causes data for an interface‐implementing type to be missing when:
- The GraphQL query contains multiple inline fragments (
... on SomeType
) for an interface, - One part of the query omits a particular implementing type, but another part includes it,
- The part that includes the omitted type appears later in the query.
As a result, Strawberry Shake’s type handling sometimes never returns the omitted type’s fields in the final result, even though the server response does include them.
In the minimal reproduction:
- The
people
field queries only Dog/Cat, omitting Bird, - The
shelters
field in the same query requests Dog, Cat, and Bird, - The first shelter actually has a
Bird
, but Strawberry Shake doesn't return it.
Repository Structure
We have two projects:
-
StrawberryShake.OrderOfInlineFragment.Bug.Web
- An ASP.NET Core app with Hot Chocolate hosting a small GraphQL schema (an interface
IPet
with multiple implementations). Program.cs
sets up the GraphQL server at/graphql
.GraphQL.cs
has the domain model (Person, Shelter, Dog, Cat, Bird, etc.).
- An ASP.NET Core app with Hot Chocolate hosting a small GraphQL schema (an interface
-
StrawberryShake.OrderOfInlineFragment.Bug.Tests
- Contains the tests (xUnit) and the Strawberry Shake queries (
WorkingQuery.graphql
,NotWorkingQuery.graphql
). - Uses
WebApplicationFactory<Program>
to spin up the Web project in‐memory. - Has four tests:
- Full fragment via Strawberry Shake client (works),
- Full fragment via raw HTTP query (works),
- Partial fragment via Strawberry Shake client (fails—the bug),
- Partial fragment via raw HTTP query (works).
- Contains the tests (xUnit) and the Strawberry Shake queries (
Three of these tests pass, but the partial‐fragment test with the Strawberry Shake client fails. The server’s JSON response does have the Bird data, so it’s not a server bug. The client just doesn’t map it due to the inline‐fragment coverage issue.