quarkusio/quarkus · error · IllegalStateException
Not a virtual method: [typeInfo: ]
Error message
Not a virtual method: [typeInfo: ]
What it means
Expression.Part.asVirtualMethod() is a narrowing conversion that only ExpressionPart instances representing virtual methods support. Calling it on a part that is not a virtual method throws this IllegalStateException including the part's toString and type info.
Source
Thrown at independent-projects/qute/core/src/main/java/io/quarkus/qute/Expression.java:137
* <ul>
* <li>type info that represents a fully qualified type name (including type parameters) -
* {@code |TYPE_INFO|<section-hint>};
* for example {@code |org.acme.Foo|},
* {@code |java.util.List<org.acme.Label>|} and {@code |org.acme.Foo|<when#123>}</li>
* <li>property; for example {@code foo} and {@code foo<loop#123>}</li>
* <li>virtual method; for example {@code foo.call(bar)} and {@code foo.getNames(10)<loop-element>}</li>
* </ul>
*
* @return the type check info
*/
String getTypeInfo();
default boolean isVirtualMethod() {
return false;
}
default VirtualMethodPart asVirtualMethod() {
throw new IllegalStateException("Not a virtual method: " + toString() + " [typeInfo: " + getTypeInfo() + "]");
}
}
/**
* Part that represents a virtual method.
*/
interface VirtualMethodPart extends Part {
List<Expression> getParameters();
}
}
View on GitHub (pinned to e1c734241f)
Solutions
- Check part.isVirtualMethod() before calling asVirtualMethod()
- Fix the template so the expression is a real method invocation with parentheses and args if a virtual method is expected
- In validation code, handle both property and method parts explicitly instead of assuming
Example fix
// before
Expression.Part part = parts.get(i);
VirtualMethodPart vm = part.asVirtualMethod(); // may throw
// after
if (part.isVirtualMethod()) {
VirtualMethodPart vm = part.asVirtualMethod();
} else {
// treat as property part
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!part.isVirtualMethod()) {
// handle as property part instead of narrowing
} Type guard
Optional<VirtualMethodPart> asVm(Expression.Part p) {
return p.isVirtualMethod() ? Optional.of(p.asVirtualMethod()) : Optional.empty();
} Try / catch
try {
VirtualMethodPart vm = part.asVirtualMethod();
} catch (IllegalStateException e) {
log.debug("Part is not a virtual method: {}", part);
} Prevention
- Always call isVirtualMethod() before asVirtualMethod()
- Handle both property and method parts in expression walkers
- Verify bundle method templates actually use method-call syntax with parentheses
- Add tests covering property-style expressions in bundle validation
When it happens
Trigger: Casting/calling part.asVirtualMethod() during expression validation or resolution when the part is actually a property/handler part, e.g. in message bundle method validation (validateMessageBundleMethodsInTemplates) or custom ValueResolver code that assumes a method part.
Common situations: Template code that treats a parameterless property access {item.name} as a method call in bundle validation, or custom extension code walking expression parts assuming all are virtual methods.
Related errors
- Tracing not enabled
- No suitable template variant found
- No template variant found
- Class [<rawClassName>] used in the parameter declaration in
- #cache cannot be used without the 'quarkus-cache' extension
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/018d38648ce11389.
Report an issue: GitHub.