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

  1. Change the method to accept and return SampleFamily (wrap values into the SampleFamily if needed)
  2. If the helper is not a chain step, remove the @MALContextFunction annotation and use it only from generated closure code or Java
  3. 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

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


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/27f0f7581e5e862a. Report an issue: GitHub.