apache/skywalking · error · IllegalArgumentException
Function {} doesn't inherit from Metrics.
Error message
Function {} doesn't inherit from Metrics. What it means
MeterSystem.create() generates a Metrics subclass at runtime (Javassist) for every metric declared by a MAL rule. The function class resolved from the FunctionRegister must both implement AcceptableValue<T> and inherit from org.apache.skywalking.oap.server.core.analysis.metrics.Metrics, because the generated class extends it and is pushed into the stream-processing pipeline. This IllegalArgumentException fires when the registered function class fails the Metrics.class.isAssignableFrom check.
Source
Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/MeterSystem.java:243
} else {
acceptance = arguments[0].getTypeName();
}
}
if (foundDataType) {
break;
}
}
}
if (!foundDataType) {
throw new IllegalArgumentException("Function " + functionName
+ " requires <" + acceptance + "> in AcceptableValue"
+ " but using " + dataType.getName() + " in the creation");
}
final CtClass parentClass;
try {
parentClass = pool.get(meterFunction.getCanonicalName());
if (!Metrics.class.isAssignableFrom(meterFunction)) {
throw new IllegalArgumentException(
"Function " + functionName + " doesn't inherit from Metrics.");
}
} catch (NotFoundException e) {
throw new IllegalArgumentException("Function " + functionName + " can't be found by javaassist.");
}
final String className = formatName(metricsName);
// Prototype-first short-circuit (fires on runtime FILTER_ONLY re-apply). Every
// runtime apply hands in a fresh {@code ClassPool}, so the pool-based existence
// check below cannot see a Metrics class the previous apply defined in a now-dead
// pool. Without this guard, every FILTER_ONLY update generated a new Metrics class,
// new MetricsStreamProcessor workers, and a new prototype that shadowed the old
// one in {@link #meterPrototypes} — a removeMetric by name could only tear down the
// latest generation, leaving prior workers + classloaders pinned forever. Match on
// scope + data type + function class; any of those differing is a genuine shape
// change and the existing IllegalArgumentException on the pool path fires below.
final MeterDefinition existingDefinition = meterPrototypes.get(metricsName);
if (existingDefinition != null
&& existingDefinition.getScopeType() == typeView on GitHub (pinned to 102af09b4a)
Solutions
- Make the custom function class extend one of the abstract bases in org.apache.skywalking.oap.server.core.analysis.meter.function (e.g. AvgFunction, SumFunction) or otherwise extend a Metrics subclass while also implementing AcceptableValue<T>
- Verify the registration entry: FunctionRegister must map the MAL function name to the class that is both a Metrics and an AcceptableValue
- Rebuild the custom function jar against the exact OAP server version deployed, then place it in oap-libs/ so the class hierarchy matches
Example fix
// before
public class MyCounter implements AcceptableValue<Long> { ... }
FunctionRegister.register("mycounter", MyCounter.class);
// after
public class MyCounter extends CounterFunction implements AcceptableValue<Long> { ... }
// CounterFunction already extends Metrics; the isAssignableFrom check now passes Defensive patterns
Strategy: validation
Validate before calling
// before registering/using a custom meter function
if (!Metrics.class.isAssignableFrom(funcClass)
|| !AcceptableValue.class.isAssignableFrom(funcClass)) {
throw new IllegalStateException(funcClass + " must extend Metrics and implement AcceptableValue");
}
FunctionRegister.register(functionName, funcClass); Type guard
boolean isValidMeterFunction(Class<?> c) {
return Metrics.class.isAssignableFrom(c)
&& AcceptableValue.class.isAssignableFrom(c);
} Prevention
- Always extend an existing function base (AvgFunction, SumFunction, ...) rather than implementing AcceptableValue from scratch
- Add a startup assertion that walks FunctionRegister and fails fast if any entry is not a Metrics
- Build custom function jars against the exact OAP version they will be deployed into
When it happens
Trigger: A MAL/LAL rule names a function whose registered implementation class implements AcceptableValue but does not extend Metrics; a custom meter function was registered into FunctionRegister with an incomplete class hierarchy (e.g. only implementing the interface); a custom function was compiled against an old SkyWalking version where the hierarchy differed.
Common situations: Writing a custom MAL function plugin: developers implement AcceptableValue but forget to extend a base class like AvgFunction; deploying a custom function jar built against an incompatible SkyWalking version; misregistered function name that collides with another non-Metrics entry.
Related errors
- Function {} can't be found by javaassist.
- {} has been defined, but calculate function or/are scope typ
- Illegal rank value {rank}, must be positive
- Incompatible ranks size = [{value.getRanks().length}] for cu
- Failed to load MAL rules
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/f72098e4a70690cd.
Report an issue: GitHub.