Skip to content

Diagnostics

Diagnostics explain why the compiler rejected a declaration and how to fix it.

When Anvil rejects source code, the diagnostic gives you the file, line, compiler code or rule name, reason, and a concrete fix.

Every diagnostic has:

  • level: error or warning
  • code: stable Anvil diagnostic code, or a compiler/Starlark rule name
  • message: what failed
  • file: source file when known
  • line: one-based source line when known
  • hint: fix instruction when Anvil can produce one
  • related: optional additional source context

Example:

api/projects.go:19: ERROR ANVIL301: invalid HTTP path "/projects/{id}": use :param path syntax instead of braces
hint: paths must start with /, use :param syntax, and cannot contain empty segments
19 | Get sdk.GET `path:"/projects/{id}"`
| ^

Errors stop generation.

Parser warnings also stop generate, manifest, openapi, and testbed because those commands require a clean scan result before producing derived artifacts. anvil scan prints parser warnings and exits successfully when no parser errors exist.

Manifest rule warnings are reported by anvil lint. Use CI policy to decide whether warnings should fail a build.

Built-in manifest rule warnings include risky but valid code, such as an unsafe HTTP method with a request type but no request-level Validate(ctx sdk.Ctx) error.

The parser and compiler validate:

  • Missing or malformed marker fields
  • Controller route table shape
  • Group nesting and inherited path metadata
  • Invalid route paths
  • Duplicate or shadowed routes
  • Handler signature shape
  • WebSocket signature shape
  • Handler signature shape for gRPC, GraphQL, and queue routes
  • Request struct binding tags
  • Duplicate request bindings
  • Unsupported binding target types
  • Validation tags on unsupported field types
  • Invalid regex patterns
  • Invalid numeric validation ranges
  • Invalid cross-field validation targets
  • Middleware method signatures
  • Unnamed middleware types
  • Dependency provider ambiguity
  • Dependency graph cycles
  • Duplicate OpenAPI operation IDs
  • Custom rule failures

Middleware errors mean the compiler found an sdk.Use[T] marker but cannot apply T safely.

ANVIL211 means the type does not implement the protocol middleware signature required at that location. For example, a GraphQL policy must use HandleGraphQL(ctx sdk.GraphQLCtx) (sdk.GraphQLResponse, error).

ANVIL220 means sdk.Use[...] was placed directly inside a GraphQL endpoint, gRPC service, or queue job. Move it to a parent sdk.Group. For GraphQL endpoint-specific middleware, use sdk.GraphQLEndpointWith[Policy].

The built-in manifest rules are:

RuleLevelPurpose
http.operation_id.uniqueErrorHTTP operation IDs must be unique for docs, clients, and testbeds.
http.request.validatorWarningUnsafe HTTP methods with request types need Validate(ctx sdk.Ctx) error for cross-field checks.
http.middleware.namedErrorHTTP middleware must be a named type so generated plans and docs stay stable.
http.route.rootWarningRoot-mounted HTTP routes are reported because they are easy to expose by accident.
http.group.emptyWarningHTTP groups with no routes in their hierarchy are reported.
http.middleware.duplicateWarningDuplicate middleware in one HTTP chain is reported.
http.route.shadowingWarningA route that shadows a child group path is reported.

Rule diagnostics use the same formatter as parser diagnostics.

Starlark rules return diagnostic dictionaries:

{
"level": "ERROR",
"rule": "company.http.write_policy",
"message": "write routes must use WritePolicy",
"hint": "use sdk.POSTWith[WritePolicy]",
"source": {"file": "api/projects.go", "line": 19},
}

If the script returns malformed diagnostics, Anvil reports the script failure as a compiler error instead of silently ignoring the rule.

When Anvil has file and line information, reports include source excerpts. This makes CI logs useful without opening an editor.

Diagnostic codes and rule names are intended for CI parsers, editor integrations, and documentation links. During the alpha cycle, parse the code with the diagnostic area and message because some parser and compiler areas reuse numeric values.