data-api-builder icon indicating copy to clipboard operation
data-api-builder copied to clipboard

[Bug]: GraphQL pagination attempts to return hasNextPage = null and fails with "Cannot return null for non-nullable field"

Open TzDeligoVision opened this issue 1 year ago • 3 comments

What happened?

We attempt to query data from an Azure SQL database table with the GraphQL interface page-by-page. For the repro we simplified the query to only fetch the primary key ThingID (PK, int, not null) and the Created (datetime2(7), null) fields and removed all filters.

query GetAllThings {
  things(
    first: 100,
    after: null,
  ) {
    items {
      ThingID
      Created
    }
    hasNextPage
    endCursor
  }
}

We get the following error response with HTTP status 200:

{
    "errors": [
        {
            "message": "Cannot return null for non-nullable field.",
            "locations": [
                {
                    "line": 10,
                    "column": 5
                }
            ],
            "path": [
                "things",
                "hasNextPage"
            ],
            "extensions": {
                "code": "HC0018"
            }
        }
    ],
    "data": {}
}

This error result is reproducible as long as we don't change the query above.

However, the result is seemingly unpredictable if we change the number of items requested:

  • with $first: 17 => OK, hasNextPage = true, endCursor has a valid value
  • with $first: 18 => error
  • with $first: 50 => error
  • with $first: 100 => error
  • with $first: 130 => OK, hasNextPage = true, endCursor has a valid value

Additional observations/cases:

  • if we move the hasNextPage and endCursor fields before the items {...} => suddenly OK with all $first values above => why does this depend on the order of the fields in the query?
  • if we remove the Created field from the items {...} (query only the ID) => suddenly OK with all $first values above => why only reproducible with the DateTime2 field in the query?
  • we remove the ID field from the items {...} (query only the Created) => the same result as before, depending on the $first value => why only reproducible with the DateTime2 field in the query?

What might be the root cause of this behaviour? Is it a reliable workaround/fix if we move the paging fields "up" before the items in our queries?

Version

1.1.7

What database are you using?

Azure SQL

What hosting model are you using?

Local (including CLI)

Which API approach are you accessing DAB through?

GraphQL

Relevant log output

dbug: Azure.DataApiBuilder.Core.Resolvers.IQueryExecutor[0]
      e2efd26f-c7ba-40d0-a626-d293fd3366a7 Executing query: SELECT TOP 101 [table0].[Created] AS [Created], [table0].[ThingID] AS [ThingID] FROM [dbo].[Thing] AS [table0] WHERE 1 = 1 ORDER BY [table0].[ThingID] ASC FOR JSON PATH, INCLUDE_NULL_VALUES
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'Hot Chocolate GraphQL Pipeline'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 POST http://localhost:5000/graphql - 200 - application/json;+charset=utf-8 217.6527ms

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

TzDeligoVision avatar Jun 27 '24 18:06 TzDeligoVision