Skip to content

Report null results for non-null fields as execution errors - #1397

Open
duckki wants to merge 2 commits into
graphql-rust:masterfrom
duckki:fix-non-nullalble-null-error
Open

duckki wants to merge 2 commits into
graphql-rust:masterfrom
duckki:fix-non-nullalble-null-error

Conversation

@duckki

@duckki duckki commented Sep 24, 2026

Copy link
Copy Markdown

A custom resolver can successfully return Value::Null for a field declared as non-null. Juniper propagates that null through the parent selection, but it does not record the field error required by GraphQL when no lower-level error caused the null.

Example

Given this schema, where the custom critical resolver returns Value::Null:

type Query {
  critical: String!
}

and this query:

query {
  critical
}

Juniper currently bubbles the null to the operation root without recording why:

{"data":null}

The response must also contain the corresponding field error:

{
  "data": null,
  "errors": [
    {
      "message": "Cannot return null for non-nullable field Query.critical.",
      "path": ["critical"]
    }
  ]
}

The focused regression is direct_null_from_non_null_field_is_reported in juniper/src/executor_tests/executor.rs. It runs the operation through both execute_sync and execute, asserting the root null and error path in both modes.

Root Cause

The sync and async object executors treat Ok(Value::Null) at a non-null field only as a propagation signal. They stop the current selection without adding a field error, assuming that some lower-level completion already recorded one.

Proposed Fix

Add an internal executor check for an existing error at or below the current field path. If a non-null field produces Ok(Value::Null) without such an error, record one non-null violation before preserving the existing bubbling behavior.

Related Reports

No exact duplicate was found. Issue #84 and issue #1287, fixed by PR #1318, concern propagating an error that already exists. This bug occurs one step earlier: resolution succeeds with Ok(Value::Null), so Juniper has no error to propagate unless the executor creates the required non-null field error.

Open PR #1256 refactors the same async execution branch but preserves the Ok(Value::Null) if is_non_null => None behavior. It overlaps at the code level but does not fix this issue.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant