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

  1. Add 'static' to every @MALContextFunction method
  2. If the method needs instance state, move that state to static fields or configuration and keep the method static
  3. 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

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


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