ID |
|
|---|---|
Status |
Backlog |
Bucket |
bug |
Priority |
3 |
Theme |
diagnostics |
Created |
2026-08-14 |
Updated |
2026-08-14 |
Root @lookupKey plus @asConnection reports a @table error the author cannot act on
Combining @asConnection with @lookupKey on a root field is rejected, which is correct, but the
message names an invariant the author never violated. Measured on a root field
filmById(film_id: [Int!]! @lookupKey, first: Int, after: String): FilmConnection @asConnection, the
field classifies to UnclassifiedField with the reason @lookupKey requires a @table-annotated
return type. The author did not write an untyped return; they wrote @asConnection on a lookup, and
the connection type the promoter minted is what is not @table-annotated. Following the advice as
given (annotate FilmConnection with @table) leads nowhere.
The cause is ordering. LookupKeyDirectiveResolver.resolveAtRoot checks only the target-table
invariant and never inspects the wrapper, so it fires first on the promoted connection type. Two
better messages already exist but are unreachable at this arm: resolveAtChild emits
@asConnection on @lookupKey fields is invalid: @lookupKey establishes a positional correspondence
… which pagination would break. Drop @asConnection or drop @lookupKey, and
GraphitronSchemaValidator.validateRootLookup emits lookup fields must not return a connection.
The validator message appears unreachable from real root SDL for the same ordering reason;
RootLookupValidationTest’s `CONNECTION_RETURN cell reaches it only through a hand-built model,
so the cube is green while the path is dead from SDL.
The likely fix is a wrapper check in resolveAtRoot ahead of the table-boundness check, reusing the
child arm’s message so both arms say the same thing, plus a pipeline-tier cell driving real SDL
through TestSchemaHelper (the existing root coverage is validator-tier only, which is how the
ordering gap stayed invisible). Worth deciding at Spec time whether the now-dead validator branch
should stay as a defence-in-depth invariant or be removed in favour of the classifier check.
Provenance: found at the third In Review gate on the lookup positional-contract item, while verifying that item’s claim that the rejection holds "on root and child fields alike". The rejection does hold; only the message is wrong, which is why this is filed separately rather than blocking it.