Build diagnostics reference¶
Every error diana_generator can report, grouped by area, with the fix.
Local errors (annotations, signatures) point at the exact source span;
graph errors are collected and reported together in a single build
failure so you can fix a batch at once.
Messages below show the pattern; X, Y, p etc. stand for your names.
Class-level rules¶
Class X combines @A and @B; a class may carry only one Diana role annotation.
A class can be a controller or a service or an advice… Split the
responsibilities into separate classes.
Diana-annotated classes must be public: generated wiring in other libraries needs to reference them.
Remove the leading underscore.
Class X declares type parameters. Generic injectables are not supported; provide a concrete subclass instead.
class Repo<T> can't be a provider. class TodoRepo extends Repo<Todo>
can — and satisfies dependencies on Repo<Todo>.
Class X is abstract and cannot be instantiated. Annotate a concrete implementation instead.
Move the annotation to the implementation; depend on the abstract type.
Class X has no public unnamed generative constructor; Diana instantiates providers through it.
Add one (factory-only and named-only classes are not injectable).
Class X is boundas: Ybut does not implement or extend it.
Fix the as: target or add the implements.
Dependency graph¶
No provider found for X — required by constructor parameter "p" of Y (package:...). Annotate a providing class with @Service/@Component, or check the type and qualifier.
Nothing in the package provides X. Also raised when only a
@Named-qualified provider exists but the parameter has no @Named.
Multiple providers implement X: A (lib), B (lib) — required by ... Disambiguate with @Named or bind one explicitly withas:.
Interface auto-binding needs exactly one implementation.
Multiple providers bound to X: ... Remove one, or qualify them withname:and select with @Named.
Two providers claim the same type as a strong binding (same class twice
via as:, or duplicated class).
Duplicate provider for X: declared in both lib_a and lib_b.
The same class (same type + qualifier) is registered twice.
Dependency cycle detected: A -> B -> A. Break the cycle, e.g. by extracting an interface or inverting one dependency.
Constructor injection cannot create cycles; restructure.
Singleton X (lib) depends on request-scoped Y: a singleton outlives every request. Make X request-scoped, or make Y a singleton.
Scope safety — see scopes.
Constructor parameter "p" of X has unsupported type T; only class types can be injected.
Function types, records and type variables aren't injectable.
Lifecycle and scheduling¶
@PostConstruct method X.y must be a public instance method with no parameters returning void or Future<void>.
(Same for @PreDestroy and @Scheduled.)
Class X declares multiple @PostConstruct methods; declare at most one.
(Same for @PreDestroy.)
@PostConstruct on X requires singleton scope; found transient.
(Same for @PreDestroy and @Scheduled — per-instance lifecycle on
transient/request providers is not supported.)
@Scheduled on X.y requires exactly one of fixedRate, fixedDelay or cron.
@Scheduled cron on X.y must have 6 fields (second minute hour day-of-month month day-of-week) or be a macro like @daily; got N.
(The shape is checked at build time; per-field range errors — e.g. an
out-of-range hour — surface when the runtime parses the expression at
startup, as a FormatException.)
JSON (@Json)¶
Unsupported field type T in @Json class X. Supported: String, int, double, bool, num, dynamic, DateTime, enums, List/Map<String, _> of supported types, and nested classes that are @Json or expose fromJson/toJson.
@Json class X has no public unnamed generative constructor.
Constructor parameter "p" of @Json class X has no matching field; @Json builds instances by matching constructor parameters to fields by name.
@Json map fields must have String keys — got Map<int, String> in X.
Actuator¶
X implements HealthIndicator but is transient-scoped; health indicators must be singletons.
Application entrypoint¶
Multiple @DianaApplication classes found: A (lib), B (lib). A package must declare exactly one application entrypoint.
Controllers and routes¶
Route method X.m must be a public instance method.
Parameter "p" of route method X.m needs exactly one binding annotation (@PathParam, @QueryParam, @Header, @Body or @Principal), or be of type DianaRequest for raw access.
Parameter "p" of route method X.m combines multiple binding annotations; use exactly one.
Parameter "p" of route method X.m must be String, int, double, bool or num (nullable allowed for @QueryParam/@Header) — got T.
Path parameter "p" of X.m is always present when the route matches; use a non-nullable type.
@Body parameter "p" of X.m has unsupported type T.
See supported body types.
X is used with @Body in Y.m but has nofactory X.fromJson(Map. Write one manually or generate it with json_serializable (both work with Diana).
X is returned from route method Y.m but has noMap. Write one manually or generate it with json_serializable (both work with Diana).
Route method X.m has unsupported return type T. Supported: a DTO with toJson(), List of DTOs, Map, String, void, DianaResponse — optionally wrapped in Future.
x.dart declares Diana members that need generated code, but is missing the part directive. Add: part 'x.diana.dart';
Copy the printed line into the file, below the imports.
Content negotiation¶
@Consumes on X.m lists no MIME types.
(Also raised for @Produces.) The list must contain at least one entry.
@Consumes on X.m requires a codec-decoded @Body parameter (Map, List or DTO); String, FormData and raw-request bodies bypass codecs.
@Produces on X.m requires a JSON-encodable return (DTO, List of DTOs, Map or List); String, void and DianaResponse returns are not negotiated.
X implements BodyCodec but is <scope>-scoped; body codecs must be singletons.
Codecs are discovered through the DI graph and wired once into the server.
Server-Sent Events¶
Route method X.m returns Stream<Y>; supported stream element types are ServerSentEvent or a DTO with toJson().
@ResponseStatus cannot be combined with a Stream return on X.m; SSE responses are always 200.
@Produces cannot be combined with a Stream return on X.m; SSE always produces text/event-stream.
gRPC¶
@GrpcService class X does not extend a grpc service base class. Extend your protoc-generated XServiceBase (package:grpc Service).
Only classes whose supertype chain reaches package:grpc's Service
qualify — your protoc-generated XServiceBase does.
Events¶
@EventListener method X.m must be a public instance method with exactly one positional parameter returning void or Future<void>.
@EventListener parameter "p" of X.m must be a non-nullable class type; found T.
The parameter is the subscribed event type — dynamic, nullable and
function types cannot be matched.
@EventListener on X requires singleton scope; found <scope>.
Listeners need a stable instance for the application's lifetime.
Authentication & authorization¶
@RolesAllowed on X lists no roles.
@Secured/@RolesAllowed on X has no effect: it is not a REST controller, WebSocket controller, gRPC service, or route method.
A silently ignored security annotation is a hole you believe is closed.
@Principal parameter "p" of X.m must be a class type.
The bound principal must be AuthPrincipal or a class subtype.
@Secured/@RolesAllowed on @GrpcService X requires exactly one singleton provider extending diana_auth's AuthenticationMiddleware; found ...
gRPC security is server-wide in this version; all @GrpcService classes must declare identical @Secured/@RolesAllowed (found differing declarations on A and B).
The @Principal binding also participates in the existing "needs exactly
one binding annotation" / "combines multiple binding annotations" errors.
Persistence¶
@Transactional/Database injection found but no DatabaseConnector provider was declared. Add a @Component extending diana_data's DatabaseConnector.
Multiple DatabaseConnector providers: A (lib), B (lib). Declare exactly one.
@Transactional class X must be extendable: remove the final/base/sealed modifier so Diana can generate a transactional proxy subclass.
@Transactional method X.m must return Future (transactions are asynchronous); found T.
@Transactional on X has no effect: it is not a @Service/@Component/@Repository provider.
Aspects¶
| Message | Fix |
|---|---|
@Timed is method-level only; annotate individual methods of X. |
Move the annotation from the class to specific methods (same for @Cacheable/@Retryable/@CircuitBreaker) |
@Timed on X has no effect: it is not a @Service/@Component/@Repository provider. |
Aspects only proxy DI providers (same template for the other aspects) |
@Timed method X.m must return Future (aspect proxies are asynchronous); found void. |
Make the method async (same template for the other aspects) |
@Timed method X.m must be a public instance method. |
Aspects cannot proxy static or private methods (same template for the other aspects) |
Aspect-annotated class X must be extendable: remove the final/base/sealed modifier so Diana can generate an aspect proxy subclass. |
Drop the modifier |
@Cacheable method X.m declares type parameters; caching generic methods is not supported. |
Cache a concrete-typed wrapper instead |
@Cacheable method X.m must return Future<T> with a non-void T (a void result cannot be cached); found Future<void>. |
Return the value you want cached |
@Cacheable on X.m requires ttlSeconds >= 1; found 0. |
Use a positive TTL (same shape for maxEntries >= 1) |
@Retryable on X.m requires maxAttempts >= 1; found 0. |
Use at least one attempt (same shape for backoffMs >= 0) |
@Retryable retryOn entries must be type literals. |
List exception types directly, e.g. retryOn: [TimeoutException] |
@CircuitBreaker on X.m requires failureThreshold >= 1; found 0. |
Use a positive threshold (same shape for resetTimeoutMs >= 1) |
@Timed name on X.m must not be empty. |
Omit name: for the default label or give a non-empty one |
Multiple DianaCacheStore providers: A (lib), B (lib). Declare exactly one. |
Keep a single pluggable cache store |
X extends DianaCacheStore but is <scope>-scoped; cache stores must be singletons. |
Make the store a singleton provider |
Query repositories¶
| Message | Fix |
|---|---|
Query repository X must extend DianaRepository<E> with a concrete class type argument. |
Give the supertype a concrete entity type |
Query repository X targets E, which is not a @Json class. Annotate E with @Json() so rows can be mapped to instances. |
Make the entity @Json |
Query repository X targets E, which is missing @Table. Annotate E with @Table('table_name'). |
Add the table mapping |
Query repository X targets E, which has no 'id' field; DianaRepository.findById/deleteById need one. |
Add an id field to the entity |
Query repository X declares aspect-annotated methods; ... Move them to a service that injects X. |
Aspects on query repos are future work |
Query repository X declares abstract member "g" which is not a method; only query methods can be abstract. |
Implement the getter/setter or remove it |
Query repository X re-declares "findAll", which is implemented by the generated repository; remove the declaration. |
The CRUD quartet comes from the base |
Query method X.m must start with findBy, findFirstBy, countBy, existsBy or deleteBy. |
Use a grammar subject prefix |
Cannot parse query method X.m at "Rest": expected a property of E followed by an optional condition. Known properties: ... |
Fix the property/condition segment |
Query method X.m mixes And and Or; a method may use only one connector. |
Split into two methods or pick one connector |
Cannot parse the OrderBy clause of query method X.m at "Rest": expected <Property>Asc or <Property>Desc. Known properties: ... |
Direction is mandatory per order property |
Query method X.m declares no conditions; add at least one property after the prefix. |
findBy alone is not a query |
OrderBy is not supported on countBy/existsBy/deleteBy (query method X.m). |
Ordering only applies to finders |
Query method X.m must declare only required positional parameters. |
No named/optional parameters |
Query method X.m declares N parameter(s) but its conditions take M. |
Match the condition arities (Between=2, IsNull=0, rest=1) |
Parameter "p" of query method X.m must be T for condition "PropOp"; got U. |
Match the property type (List<T> for In/NotIn) |
Condition "PropOp" of query method X.m needs a String-typed property; 'p' of E is T. |
Like/Contains/StartsWith/EndsWith need String columns |
Query method X.m must return Future<List<E>> (findBy); got T. |
Per-subject contract (variants for findFirstBy/countBy/existsBy/deleteBy) |
Query method X.m must not declare type parameters. |
Query methods are monomorphic |
Query method X.m combines In with the Or connector, which the query builder cannot express; use And. |
knex 1.3 has no orWhereIn |
The database-connector message now reads
@Transactional/Database/DianaRepository usage found but no DatabaseConnector provider was declared. ....
STOMP messaging¶
| Message | Fix |
|---|---|
@MessageMapping method X.m must be a public instance method with one or two positional parameters: the payload (String or an @Json class), optionally followed by a StompMessage. |
Fix the signature |
@MessageMapping payload parameter "p" of X.m must be String or a class annotated with @Json; found T. |
Use a String or @Json payload |
@MessageMapping second parameter of X.m must be StompMessage from package:diana; found T. |
The context parameter is StompMessage |
@MessageMapping method X.m returns T; return values must be String or an @Json class (wrapped in Future if async). |
Return String/@Json/void |
@MessageMapping method X.m returns a value but has no @SendTo destination. Add @SendTo('/topic/...') or return void. |
Pair a returning handler with @SendTo |
@SendTo on X.m requires a non-void return value to publish. |
Remove @SendTo or return a value |
@SendTo on X.m requires @MessageMapping on the same method. |
@SendTo only pairs with @MessageMapping |
@MessageMapping destination "d" on X.m must start with "/". |
Destinations are absolute (same for @SendTo) |
@MessageMapping on X requires singleton scope; found s. |
Handlers live on singletons |
Class X (lib) extends StompEndpoint but is not annotated with @WebSocketController. ... |
Annotate the endpoint |
X extends StompEndpoint but is <scope>-scoped; STOMP endpoints must be singletons ... |
Make it a singleton |
@MessageMapping destination "d" is handled by both A.m1 (lib) and B.m2 (lib). Destinations must be unique across the application. |
One handler per destination |
@MessageMapping methods were found but no @WebSocketController extends StompEndpoint. ... |
Declare an endpoint |
Malformed inbound frames do not surface as build errors — at runtime the
broker replies with an ERROR frame (malformed frame: ...) and closes the
connection.
Observability¶
Multiple DianaObservability providers: A (lib), B (lib). Declare exactly one.
The server, scheduler, bus and database all share one observer instance.
X extends DianaObservability but is <scope>-scoped; observability providers must be singletons.
Middleware¶
X, referenced by @GlobalMiddleware, is not an injectable class. Annotate it with @Component (or another injectable annotation).
Also raised for @UseMiddleware on Controller /
@UseMiddleware on Controller.method.
X, referenced by ..., does not implement Diana's Middleware interface.
X, referenced by ..., is request-scoped; middleware must be singletons.
(Also applies to @UseMiddleware on @WebSocketController X — handshake
interceptors.)
@UseMiddleware entries must be type literals.
Only @UseMiddleware([SomeType]) — no expressions.
WebSockets¶
@WebSocketController class X (lib) does not implement Diana's WebSocketHandler interface. Implement it, or extend BaseWebSocketHandler.
Duplicate WebSocket path "/ws/x": handled by both A and B.
Each endpoint path maps to exactly one handler class.
@WebSocketController class X cannot be request-scoped; use Scope.singleton (shared handler) or Scope.transient (one handler per connection).
Configuration¶
@Value parameter "p" of X must be String, int, double, bool or num — got T.
@Value defaultValue must be a String, int, double or bool literal.
@ConfigurationProperties class X has no public unnamed generative constructor.
Constructor parameter "p" of @ConfigurationProperties class X must be String, int, double, bool or num (nullable for optional keys) — got T.
Exception handling¶
@ControllerAdvice class X declares no @ExceptionHandler methods.
@ExceptionHandler on X.m must reference a class type.
Exception handler X.m must take (E) or (E, DianaRequest).
The first parameter's type must be exactly the annotated exception type;
the optional second must be DianaRequest.
Exception handler X.m must return DianaResponse (or Future<DianaResponse>).
Validation¶
@Min on X.f requires a numeric field — got T.
Analogous messages for each constraint: @Max (numeric), @NotBlank,
@Email, @Pattern (String), @NotEmpty, @Size (String, List, Set or
Map).
@Valid on X.f cascades into T, which has no constraint annotations.
Add constraints to the nested type, or drop @Valid.
Runtime startup errors¶
Not build errors, but startup failures worth knowing:
ConfigException: Missing required config key "k" (checked the YAML config file and environment variable "K").
A @Value without default or a non-nullable @ConfigurationProperties
key is absent from every source.
ConfigException: Config key "k" has value "v" (RuntimeType), which cannot be read as T.
The configured value can't be coerced — fix the YAML/env value.