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

  1. Check part.isVirtualMethod() before calling asVirtualMethod()
  2. Fix the template so the expression is a real method invocation with parentheses and args if a virtual method is expected
  3. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/018d38648ce11389. Report an issue: GitHub.