Diagnosing Groovy 4.x Static Type-Checking Runtime Failures
Resolve Groovy 4.x MissingMethodException errors caused by @TypeChecked. This diagnostic guide covers classpath gaps, signature mismatches, and how to handle dynamic dispatch in static contexts.
11 Jul 2025, 05:44 UTC

The Problem: Runtime Failures After Enabling Type Checking
In Groovy 4.x, adding the @TypeChecked annotation or enabling global type-checking via groovy.config can transform a working script into one that throws groovy.lang.MissingMethodException or java.lang.NoSuchMethodException. This happens because static type checking requires the compiler to resolve every identifier against the classpath at compile time. If the compiler cannot find a class or method signature, it may fail to generate the correct call site, leading to a runtime crash despite the script appearing syntactically correct.
Diagnostic Summary
Use this table to quickly match your symptoms to the likely root cause.
| Symptom | Likely Cause | Primary Diagnostic Tool |
|---|---|---|
MissingMethodException only when @TypeChecked is present |
Missing import or classpath gap | -Dgroovy.typecheck=true |
| Failure occurs only in production/CI environment | Groovy version mismatch | groovy -version |
| Error on a method known to be added via MetaClass/dynamic logic | Static check vs. Dynamic dispatch conflict | Code review for invokeMethod |
| Method exists in library but is "not applicable" | Signature mismatch or generic type erasure | IDE Type Inspector / Compiler logs |
Ordered Diagnostic Checks
-
Verify Environment Parity
Ensure the Groovy version is identical across development and deployment environments. Run the following command in both locations:
groovy -versionDifferences in versions can lead to different compiler behaviors regarding
@CompileStaticand@TypeCheckeddefaults. -
Force Compile-Time Diagnostics
Instead of relying on runtime failures, force the Groovy compiler to emit diagnostics during execution. Run your script with the type-check flag:
groovy -Dgroovy.typecheck=true script.groovyThe compiler will now output the exact line and identifier it cannot resolve, allowing you to pinpoint the missing symbol before the script even executes.
-
Validate Classpath Availability
If the diagnostics point to a missing class from a third-party library, verify the JAR is explicitly provided. For example, if using Apache Commons Lang, run:
groovy -cp lib/commons-lang3-3.12.0.jar script.groovyIf the error disappears, the issue is a classpath gap in your deployment configuration.
-
Check for Missing Explicit Imports
Groovy's dynamic nature often hides missing imports. Static checking does not. If a class is unresolved, add an explicit import at the top of the script (e.g.,
import java.util.List) and re-run the diagnostic check.
Fixes Based on Findings
Scenario A: The method is truly dynamic
If you are using invokeMethod, methodMissing, or adding methods to the MetaClass at runtime, static checking will fail because these methods do not exist in the bytecode. To fix this, relax the check for that specific block:
@TypeChecked(ignores = ["MissingMethodException"])
void callDynamicLogic() {
// Dynamic method calls here
}
Scenario B: Signature Mismatch
If the error states the method is "not applicable for argument types," verify the parameter types. Groovy 4.x is stricter with @CompileStatic and @TypeChecked. Ensure you are passing the exact type expected by the API, or cast the variable explicitly to the required type.
Scenario C: Classpath/Import Gap
Add the missing JAR to your CLASSPATH environment variable or the -cp flag, and add the corresponding import statement to the script.
Concrete Example: The ArrayList Pitfall
Consider this script in Groovy 4.x:
@TypeChecked
class DataProcessor {
void process() {
def list = new ArrayList()
list.addAll([1, 2, 3]) // Potential failure point
}
}
Without @TypeChecked, this works via dynamic dispatch. With it, you may see MissingMethodException because def list is inferred as ArrayList (raw type), and the compiler may struggle to match the addAll(Collection) signature against the Groovy list [1, 2, 3].
The Fix: Use explicit generics to help the compiler:
ArrayList<Integer> list = []
list.addAll([1, 2, 3])
Escalation Criteria
If the following conditions are met, escalate the issue to the library vendor or the Groovy community:
- The JAR is confirmed present on the classpath via
-cp. - The Groovy version is consistent across environments.
- The method exists in the library's official documentation for that specific version.
- The error persists even after explicit casting and imports.
When escalating, provide the failing script, the full stack trace, and your groovy.config file.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.