apache/skywalking · error · IllegalArgumentException
@MALContextFunction {}.{}() must be static
Error message
@MALContextFunction {}.{}() must be static What it means
Startup-time SPI validation error from MalExtensionRegistry: a class implementing MalFunctionExtension declares a method annotated @MALContextFunction that is not static. The v2 compiler generates direct static calls (e.g. com.example.MyExtension.myMethod(sf, args)) with no receiver object, so non-static methods cannot be supported and registration aborts with IllegalArgumentException during ServiceLoader scanning at OAP boot.
Source
Thrown at oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java:77
ServiceLoader.load(MalFunctionExtension.class)) {
register(ext);
}
}
private static void register(final MalFunctionExtension ext) {
final String namespace = ext.name();
if (namespace == null || namespace.isEmpty()) {
log.warn("Skipping MalFunctionExtension with null/empty name: {}",
ext.getClass().getName());
return;
}
final Map<String, ExtensionMethod> methods = new HashMap<>();
for (final Method m : ext.getClass().getMethods()) {
if (!m.isAnnotationPresent(MALContextFunction.class)) {
continue;
}
if (!Modifier.isStatic(m.getModifiers())) {
throw new IllegalArgumentException(
"@MALContextFunction " + ext.getClass().getSimpleName()
+ "." + m.getName() + "() must be static");
}
final Class<?>[] paramTypes = m.getParameterTypes();
if (paramTypes.length == 0
|| !SampleFamily.class.isAssignableFrom(paramTypes[0])) {
throw new IllegalArgumentException(
"@MALContextFunction " + ext.getClass().getSimpleName()
+ "." + m.getName()
+ "() first parameter must be SampleFamily");
}
if (!SampleFamily.class.isAssignableFrom(m.getReturnType())) {
throw new IllegalArgumentException(
"@MALContextFunction " + ext.getClass().getSimpleName()
+ "." + m.getName()
+ "() return type must be SampleFamily");
}
final Class<?>[] extraParamTypes = new Class<?>[paramTypes.length - 1];View on GitHub (pinned to 102af09b4a)
Solutions
- Add 'static' to every @MALContextFunction method
- If the method needs instance state, move that state to static fields or configuration and keep the method static
- Rebuild the extension jar; restart OAP and confirm the 'Registered MAL extension function' log line appears
Example fix
// before
@MALContextFunction
public SampleFamily transform(SampleFamily sf, double factor) { ... }
// after
@MALContextFunction
public static SampleFamily transform(SampleFamily sf, double factor) { ... } Defensive patterns
Strategy: validation
Validate before calling
for (Method m : ext.getClass().getMethods()) {
if (m.isAnnotationPresent(MALContextFunction.class)
&& !Modifier.isStatic(m.getModifiers())) {
throw new IllegalArgumentException("Non-static @MALContextFunction: " + m);
}
} Try / catch
raised at OAP startup during SPI scan; catch at bootstrap is not useful — fix the extension and redeploy
Prevention
- Copy the canonical extension example from the meter-analyzer docs
- Add an extension unit test that boots MalExtensionRegistry.init() so signature errors fail the build, not production
When it happens
Trigger: Writing an extension method as an instance method: 'public SampleFamily transform(SampleFamily sf, double f)' with @MALContextFunction but without 'static'. The check Modifier.isStatic(m.getModifiers()) fails for the annotated method.
Common situations: First-time extension authors copying instance-style helper methods into the extension class; IDE auto-generating an instance method; refactoring that accidentally drops the static modifier.
Related errors
- @MALContextFunction {}.{}() first parameter must be SampleFa
- @MALContextFunction {}.{}() return type must be SampleFamily
- @MALContextFunction {}.{}() List parameters must be List<Str
- Duplicate @MALContextFunction name '{}' in namespace '{}' fr
- Duplicate MAL extension namespace '{}' from {}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/c316e9594daff487.
Report an issue: GitHub.