E05260: dispatcher on sealed type must have handlers for all permitted types
What went wrong
A dispatcher method's parameter type is a sealed type (a trait or class with an 'allow only' clause), but the dispatcher class does not have handlers for all permitted types. When a type declares its complete set of concrete implementations via 'allow only', the compiler can verify that the dispatcher handles every possible runtime type — providing compile-time exhaustiveness checking similar to Java's sealed switch or Kotlin's sealed when.
This works identically for both sealed traits and sealed classes.
The dispatcher entry point (marked 'as dispatcher') acts as the declarative marker. Each permitted type in the 'allow only' list must have a corresponding handler method with the same name and a parameter of that specific type. Missing handlers mean that at runtime, certain types would fall through to the generic entry point rather than being handled specifically — defeating the purpose of the sealed type pattern.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 618 (How do sealed dispatchers enforce exhaustive handler cove...)
How to fix it
Add handler methods for all types listed in the sealed type's 'allow only' clause. Each handler must have the same method name as the dispatcher entry point and accept a parameter of the specific permitted type.
This exhaustiveness requirement is the primary value of sealed types: when a new type is added to the 'allow only' list, every dispatcher that operates on that type will fail to compile until a handler is added. This guarantees that all dispatch points are updated — no runtime surprises.
Common causes
- Adding a new type to the 'allow only' list without updating dispatchers
- Forgetting to add a handler for one of the permitted types
- Relying on the generic entry point to handle specific types
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E05260: dispatcher on sealed type must have handlers for all permitted types
#!ek9 defines module error.e05260.bad defines trait Shape allow only Circle, Square, Triangle area() as abstract <- rtn as Float? defines class Circle with trait of Shape override area() <- rtn as Float: 3.14 Square with trait of Shape override area() <- rtn as Float: 1.0 Triangle with trait of Shape override area() <- rtn as Float: 0.5 <?- IncompleteProcessor only handles Circle. Missing handlers for Square and Triangle. -?> IncompleteProcessor process() -> circle as Circle content <- "Circle" require content? process() as dispatcher -> shape as Shape content <- "Unknown shape" require content? <?- CompleteProcessor handles all three types. No error expected — all permitted types are covered. -?> CompleteProcessor process() -> circle as Circle content <- "Circle" require content? process() as dispatcher -> shape as Shape content <- "Unknown shape" require content? process() -> square as Square content <- "Square" require content? process() -> triangle as Triangle content <- "Triangle" require content?
Fixed: Give the dispatcher a handler for every type the sealed trait allows
#!ek9 defines module error.e05260.good defines trait Shape allow only Circle, Square, Triangle area() as abstract <- rtn as Float? defines class Circle with trait of Shape override area() <- rtn as Float: 3.14 Square with trait of Shape override area() <- rtn as Float: 1.0 Triangle with trait of Shape override area() <- rtn as Float: 0.5 CompleteProcessor process() -> circle as Circle <- rtn as String: "Circle" process() as dispatcher -> shape as Shape <- rtn as String: "Unknown shape" process() -> square as Square <- rtn as String: "Square" process() -> triangle as Triangle <- rtn as String: "Triangle"
Questions and answers
These Q&A entries show E05260 and its fix: