GraphQL / Editorial solution guide
Diagnose partial data, null propagation and access policy
Explain a missing object or field without confusing absence, source failure and intentional access denial.
Read-only knowledge base · No public comments
Recognize the symptoms
A card disappears after one optional source fails, a nested field becomes null, or two graph paths expose different visibility for the same course. The response can contain useful data and errors together. A null value by itself does not establish whether a record is absent, hidden or unavailable under the application’s documented policy.
Understand the likely causes
- Likely causes include an overstrong non-null promise, an execution exception, inconsistent policy between resolvers, a request-scoped loader used globally, or a client that discards all data whenever errors is present. A skipped field is absent from the response, which is another case distinct from a present null.
Inspect data, error paths and the exact selected type
Preserve the redacted response envelope and matching operation. Read errors.path as response coordinates, including aliases and list indices, and compare the selected field’s nullability chain in the exact schema release. A failure at a non-null leaf can replace its nearest nullable parent, so the apparent missing object may be a consequence rather than the initial fault. Locations refer to source positions and do not identify database records. Treat extension codes as application-specific unless the chosen implementation explicitly documents a shared contract.
Reproduce the intended failure boundary locally
With a synthetic source, make summary fail while title succeeds. Under nullable summary, the expected envelope can preserve title and mark summary unavailable. Then repeat with the actual schema contract to observe whether propagation removes course or a wider parent. Do not change non-null to nullable simply to hide an underlying data corruption problem; first decide the domain’s legitimate failure boundary. The JSON below illustrates one declared nullable contract and is not an observed response from a running server.
{"data":{"course":{"title":"Graph foundations","summary":null}},"errors":[{"message":"Summary unavailable","path":["course","summary"]}]}
The fixture preserves course.title. A different non-null chain can legitimately produce a different data boundary.
Review all paths and cache lifetimes
If Query.course is hidden but author.courses returns the same course, compare the domain service methods and principal scope rather than weakening the root check. Authorization should be enforceable wherever the object or protected field is resolved, including mutation payloads. A global loader may return a value cached under another principal without rechecking visibility. Reproduce sequential synthetic callers with the same ID and different tenants, and inspect loader creation and key scope. Keep absence and denial publicly indistinguishable when that is the declared disclosure policy; do not introduce an existence leak while debugging.
Repair presentation without inventing completeness
After server behavior is correct, review the client’s error policy. A descriptive view may render authorized partial data with a clear unavailable region, while a sensitive decision may require a complete fresh read. Do not turn failed permission data into a permissive default or replace every null collection with an empty list without considering meaning. A skipped field should be handled as absent, not as a server claim of null. Keep result reconciliation tied to the current principal so a late response cannot restore a previous user’s private view.
Verify the fix
Verify source failure, legitimate absence, denied access, conditional omission and a successful result separately. Assert the precise data boundary and safe error path. Exercise both root and nested routes with eligible and ineligible principals, and test an account switch while a response remains pending. No live authorization or GraphQL engine test is claimed by this editorial guide.
Keep it from recurring
- Document null semantics and independent source failure domains in schema review. Centralize domain visibility, create loaders within the correct identity lifecycle and keep paired policy fixtures. Design client partial-data behavior for each workflow instead of adopting a global discard-all or accept-all rule.