You probably arrived here because the build failed with a [<kind>] <message> line and you searched for it. The rest of this page is organised so the line you saw is the entry point: top-level kinds first, then the nine unknown-name attempt kinds (the most common shape), then the four deferred emit-block reasons, and finally the handful of structural errors common enough to be worth naming individually. Each entry leads with a sample line you can grep for.

Reading an error line

Every emitted error takes one of three forms. Pattern-match by prefix:

[author-error] <message> [; did you mean: A, B, C]
[invalid-schema] <message>
[deferred] <message>

The did you mean: …​ suffix only appears for UnknownName variants (the nine attempt-kinds in this page); a structural [author-error] carries no candidate list. A [deferred] message is a self-contained statement that the feature is recognised but not yet generated; it carries no further suffix.

Watch-mode (mvn graphitron:dev) groups errors by file and coordinate, then prints them under one heading per element; the [<kind>] prefix is preserved through the grouping so the typed signal is still legible.

Most everyday [invalid-schema] and [author-error] errors are Structural variants whose messages are produced ad-hoc at the classifier site; their text is not enumerable here, but the kind-level entries below describe what reading them looks like.

Top-level kinds

Three prefixes. Triage by which one you saw.

author-error

Sample line. [author-error] @field 'firstName' did not match any column on table 'customer'; did you mean: FIRST_NAME, LAST_NAME, EMAIL.

Cause. Author-correctable: a name typo, a missing @table somewhere it’s needed, a directive pointed at something the jOOQ catalog or SDL registry doesn’t know about. When the lookup is against a closed set, the message includes a did you mean: …​ hint with up to five candidates ranked by Levenshtein distance.

Next step. The fix is in the schema or the consumer code (a column rename, an FK declaration, a corrected className:); no Graphitron-internal change is needed. If the message includes did you mean: …​, the relevant attempt-kind below names the resolution rule. When you can’t tell whether an error is [author-error] or [invalid-schema], the rule of thumb is "could a column rename in the SDL fix it?" Yes → [author-error]. No → [invalid-schema].

invalid-schema

Sample line. [invalid-schema] @asConnection on a non-@splitQuery field that returns a paginated child or [invalid-schema] lookup fields must not return a connection.

Cause. The directive combination cannot work, period. Two sub-shapes:

  • DirectiveConflict reports two or more directives that co-occur in a combination the classifier rejects (@asConnection on a non-@splitQuery field, @discriminate mixed with @reference). The error names the conflicting directives.

  • Structural reports rules that don’t reduce to a clean directive enumeration ("lookup fields must not return a connection", "result type does not match input cardinality").

Next step. Drop or replace one of the directives, or restructure the schema so the combination doesn’t arise. Renames don’t help; this is a hard "no". The directive pages in the directive reference document the admitted directive combinations per directive.

deferred

Sample line. [deferred] split-batch emitter does not yet support @condition with a join step.

Cause. Recognised but not yet generator-supported. The classifier understands what the schema asks for, but emission is stubbed until support ships.

Next step. Either drop the unsupported shape (and revisit when support ships), or contribute the missing emission to the rewrite. The message states which shape is unsupported; the emit-block reasons further down this page describe each shape that currently lands here.

Unknown name: which kind of name

When [author-error] carries an UnknownName variant (a closed-set name lookup that didn’t resolve), the message contains a did you mean: …​ suffix when there were close candidates. The variant’s attempt-kind field names what kind of thing the classifier was looking up; the LSP fix-its read this typed value to offer the right action ("rename column", "correct the class name", etc.). Find your sample below.

column

Sample line. [author-error] @field 'firstName' did not match any column on table 'customer'; did you mean: FIRST_NAME.

Cause. The @field directive’s name: argument did not match any column on the @table-bound parent. Typical typos: case (firstName vs FIRST_NAME) or a stale rename (column dropped at the database side, schema not updated).

Next step. Correct the name: argument, or update the database schema and regenerate the jOOQ catalog if the column was supposed to exist. @field directive reference covers the column-name resolution rules.

table

Sample line. [author-error] @table 'CUSTOMER' did not match any table in the catalog; did you mean: customer.

Cause. The @table directive’s name: argument did not match any table in the jOOQ-generated catalog. Candidates are tables under the configured <jooqPackage>.

Next step. Correct case or schema prefix. If the table is genuinely missing, regenerate the jOOQ catalog from the database first. @table directive reference covers the resolution rules.

foreign-key

Sample line. [author-error] @reference key 'customer_address_fkey' did not match any FK on table 'customer'; did you mean: customer_address_id_fkey.

Cause. The @reference directive’s key: argument did not match any FK declared on the parent table. Candidates are the FK constants on the relevant table’s Keys class.

Next step. Correct the constraint name. If the FK exists in the database but not in the catalog, regenerate jOOQ. If the FK doesn’t exist, declare it (ALTER TABLE …​ ADD FOREIGN KEY) or pin the join with table: instead of key:. @reference directive reference covers both pinning shapes.

service-method

Sample line. [author-error] @service method 'findCustomers' not found on com.example.CustomerService; did you mean: findCustomer.

Cause. The @service (or @externalField) directive’s methodName: argument (or the field-name default) did not match any static method on the resolved class. Candidates are the public static methods on that class with matching arity.

Next step. Correct the method name or rebind via argMapping: if the parameter list shifted. How-to: Wire external Java code covers the FQCN + method-name contract.

lifter-method

Sample line. [author-error] @sourceRow method 'liftKeys' not found on com.example.Lifters; did you mean: liftKey.

Cause. The @sourceRow directive’s methodName: argument did not match any static method on the resolved class. Candidates are the lifter-shape static methods ((Set<Key>) → Map<Key, Value>) on that class.

Next step. Correct the method name. The lifter must be a static method with the (Set<Key>) → Map<Key, Value> shape.

enum-constant

Sample line. [author-error] @enum constant 'PENDING' not found on com.example.Status; did you mean: PENDING_REVIEW.

Cause. A jOOQ-typed @enum mapping referenced a Java enum constant the resolved enum class doesn’t carry.

Next step. Correct the constant name, or update the jOOQ catalog if the database enum changed.

type-name

Sample line. [author-error] @nodeId typeName 'customer' did not match any GraphQL type; did you mean: Customer.

Cause. A @nodeId directive’s typeName: argument (or a similar refType lookup) did not match any GraphQL type in the assembled SDL.

Next step. Correct case or pull in the missing schema file. @nodeId directive reference covers the typeName resolution.

nodeid-key-column

Sample line. [author-error] @node keyColumns 'customer_id' did not match a column on table 'customer'; did you mean: CUSTOMER_ID.

Cause. A @node directive’s keyColumns: argument named a column the bound table doesn’t carry.

Next step. Correct case (jOOQ-generated identifiers are usually upper-snake) or update keyColumns: after a schema change. @node directive reference covers the keyColumns: contract.

dml-kind

Sample line. [author-error] @mutation typeName 'CREATE' is not a supported DML kind; did you mean: INSERT.

Cause. A @mutation directive’s typeName: argument did not match the closed set of supported DML kinds.

Next step. Use one of the supported values (INSERT, UPDATE, DELETE, UPSERT). @mutation directive reference covers the supported kinds.

Named structural errors

Structural [author-error] messages are written at the classifier site and are mostly not enumerable, as the kind entry above says. The one below is listed anyway because it is the error a schema meets by writing the obvious thing rather than a wrong thing, and because both of its remedies are fixed directives rather than a rename you have to work out.

An argMapping path that does not resolve

Sample line. [author-error] @routine argMapping entry 'pCustomerId: input.custmerId': segment 'custmerId' does not exist on input type 'RentFilmInput'; did you mean: customerId.

Cause. The right-hand side of an argMapping entry names a GraphQL slot and then walks into nested input fields. One message serves every directive that accepts an argMapping (@service, @condition, @routine, @tableMethod) because the path namespace is the same at all of them; only the site prefix differs. Two shapes reach it: a head segment that names no slot in scope, which lists the slots that are, and a later segment that names no field on the input type at that depth, which suggests the near miss.

Next step. Correct the segment. Binding a parameter to a nested input field is the canonical description of the form.

@routine adds three rejections on top, because a routine IN parameter is resolved from the database catalog rather than by reflection:

  • @routine argMapping names parameter 'pEnvv', which is not an IN parameter of routine 'rentFilm' (the left-hand side named no routine parameter). Check the jOOQ-generated camelCased name.

  • @routine parameter 'pEnv' has no binding: a routine parameter was neither named by an argMapping / columnMapping entry nor matched by an identically-named GraphQL argument.

  • @routine parameter 'pEnv' binds to 'input', whose GraphQL type 'RentFilmInput' is not a scalar or enum: the path stopped on an input object. A routine IN parameter takes one value; bind a scalar field inside it.

A node’s id field shadowing a column named id

Sample line. [author-error] field 'Doc.id': table 'doc' has a column named 'id' and also publishes node metadata, so 'id' is ambiguous. Add @nodeId to publish the global ID, or @field(name: "id") to expose the raw column.

Cause. The type is a node, so its id field is a candidate for the encoded global ID; the bound table also has a column of that name, so it is equally a candidate for that column’s value. Both readings are legitimate and they are different values on the wire, so the classifier refuses to pick one for you. The wording of the first clause varies with where the node identity came from: a table publishing \__NODE_TYPE_ID / \\__NODE_KEY_COLUMNS is named as such, and a type that declared @node explicitly is named as a node type over its table.

Next step. Write the reading you meant on the field. @nodeId publishes the encoded global ID; @field(name: "id") exposes the raw column, at the cost of that type no longer round-tripping through Query.node(id:). The @node reference covers both.

Drift protection

DiagnosticsDocCoverageTest asserts every value of RejectionKind and Rejection.AttemptKind has an anchored === <kebab-case-name> heading on this page, and every such heading corresponds to an enum value. A new diagnostic added to one of these enums cannot land green without a doc paragraph; an obsolete code’s removal forces the heading’s removal.

Structural variants (AuthorError.Structural, InvalidSchema.Structural, InvalidSchema.DirectiveConflict) carry ad-hoc messages produced at the classifier site and are not enumerable; the kind-level entries above describe how to read those. Named structural errors is outside the test’s scope for the same reason: those entries are chosen editorially, so nothing forces one to exist and nothing forces one to be removed.

See also

  • Directive reference is the SDL-side companion: every closed-set name lookup that produces an unknown-name error resolves against a directive’s argument, and the directive page covers the resolution contract.

  • Maven plugin configuration covers the validate goal that runs the validator without emitting code; useful for a CI gate that surfaces these errors without the full code-generation cost.

  • How-to: Migrating from the legacy generator covers diagnostics specific to the legacy-to-rewrite transition (the @notGenerated rejection, the retired global-ID inferences, the @condition cascade divergence).