apache/skywalking · error · IllegalArgumentException
@MALContextFunction {}.{}() return type must be SampleFamily
Error message
@MALContextFunction {}.{}() return type must be SampleFamily What it means
SPI validation error from MalExtensionRegistry: a @MALContextFunction method's return type is not assignable to SampleFamily. Because every extension call is a chain step (metric.ns::method(...).nextStep(...)), the generated code reassigns the chain variable to the call's result, which must therefore be a SampleFamily.
Source
Thrown at oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/rt/MalExtensionRegistry.java:90
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];
System.arraycopy(paramTypes, 1, extraParamTypes, 0, extraParamTypes.length);
// Validate List params use List<String> (the only List type MAL supports)
final Type[] genericTypes = m.getGenericParameterTypes();
for (int i = 1; i < genericTypes.length; i++) {
if (List.class.isAssignableFrom(extraParamTypes[i - 1])
&& genericTypes[i] instanceof ParameterizedType) {
final Type elementType =
((ParameterizedType) genericTypes[i])
.getActualTypeArguments()[0];
if (!String.class.equals(elementType)) {
throw new IllegalArgumentException(
"@MALContextFunction " + ext.getClass().getSimpleName()
+ "." + m.getName()View on GitHub (pinned to 102af09b4a)
Solutions
- Change the method to accept and return SampleFamily (wrap values into the SampleFamily if needed)
- If the helper is not a chain step, remove the @MALContextFunction annotation and use it only from generated closure code or Java
- Rebuild the extension jar and restart OAP
Example fix
// before
@MALContextFunction
public static boolean isHot(SampleFamily sf) { ... }
// after
@MALContextFunction
public static SampleFamily hotOnly(SampleFamily sf) { return sf.filter(...); }
// or, if not a chain step: drop the annotation Defensive patterns
Strategy: validation
Validate before calling
if (!SampleFamily.class.isAssignableFrom(m.getReturnType())) {
throw new IllegalArgumentException("Return type must be SampleFamily: " + m);
} Try / catch
startup-time; fix the extension and redeploy
Prevention
- Chain steps return SampleFamily; helpers that don't should not carry the annotation
- Review annotations whenever refactoring return types
When it happens
Trigger: Methods returning void, boolean, double, String, or any non-SampleFamily type while carrying @MALContextFunction. The check SampleFamily.class.isAssignableFrom(m.getReturnType()) fails at registry init during OAP startup.
Common situations: Annotating predicate helpers (boolean) or value extractors (double) that were meant for use inside closures, not as chain steps; refactoring a chain method to return an intermediate internal type.
Related errors
- @MALContextFunction {}.{}() first parameter must be SampleFa
- @MALContextFunction {}.{}() must be static
- @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/27f0f7581e5e862a.
Report an issue: GitHub.