apache/skywalking · error · IllegalArgumentException

{} has been defined, but calculate function or/are scope typ

Error message

{} has been defined, but calculate function or/are scope type is/are different.

What it means

MeterSystem keeps a pool-level check for already-generated metric classes: if a class named org.apache.skywalking.oap.server.core.analysis.meter.<FormattedName> already exists in the pool, it is only reusable when its superclass (the calc function) and the registered scope type are identical to the new request. Otherwise creation is rejected with this IllegalArgumentException — the metric name is a stable identity and its shape cannot silently change.

Source

Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/MeterSystem.java:272

        // 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() == type
            && existingDefinition.getDataType().equals(dataType)
            && existingDefinition.getMeterPrototype().getClass().getSuperclass() == meterFunction) {
            log.debug("Metric {} already registered with matching shape; reusing existing "
                + "Metrics class + workers (FILTER_ONLY re-apply path).", metricsName);
            return;
        }
        try {
            CtClass existingMetric = pool.get(METER_CLASS_PACKAGE + className);
            if (existingMetric.getSuperclass() != parentClass
                || type != meterPrototypes.get(metricsName).getScopeType()) {
                throw new IllegalArgumentException(
                    metricsName + " has been defined, but calculate function or/are scope type is/are different.");
            }
            log.info("Metric {} is already defined, so skip the metric creation.", metricsName);
            return;
        } catch (NotFoundException ignored) {
            // proceed — class not yet defined in this pool
        }
        CtClass metricsClass = pool.makeClass(METER_CLASS_PACKAGE + className, parentClass);
        try {
            metricsClass.addConstructor(CtNewConstructor.make("public " + className + "() {}", metricsClass));
            metricsClass.addMethod(CtNewMethod.make(
                "public org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue createNew() {"
                    + "    org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue meterVar = new " + METER_CLASS_PACKAGE + className + "();"
                    + "    ((org.apache.skywalking.oap.server.core.analysis.meter.Meter)meterVar).initMeta(\"" + metricsName + "\", " + type.getScopeId() + ");"
                    + "    return meterVar;"
                    + "}",
                metricsClass));
        } catch (CannotCompileException e) {

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Pick a new metric name for the new shape (e.g. endpoint_qps_avg vs endpoint_qps_sum) and update dashboards/queries accordingly
  2. If the old shape must be replaced, remove it first via MeterSystem.removeMetric / rule hot-remove, or restart the OAP server so pools start clean
  3. Audit all active MAL/LAL/OAL rules for duplicate metric names with differing function or scope declarations

Example fix

# before (two rules, same metric name, different function)
endpoint_sla = avg(otel...http_server_duration);
endpoint_sla = sum(otel...http_server_duration);

# after
endpoint_sla_avg = avg(otel...http_server_duration);
endpoint_sla_sum = sum(otel...http_server_duration);
Defensive patterns

Strategy: try-catch

Try / catch

try {
    meterSystem.create(name, func, type, dataType);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("has been defined")) {
        log.warn("Metric {} redefined with a different shape; rename or remove it first", name);
    }
    throw e;
}

Prevention

When it happens

Trigger: Two MAL rules (or a rule re-applied after edit) declare the same metric name with different functions, e.g. avg then sum; the same metric name is declared with different ScopeType (Service vs Endpoint) in separate rules; an OAL metric and a MAL metric collide on the generated class name in the same pool.

Common situations: Hot-updating a MAL config where the operator changed the aggregation function or scope of an existing metric without an OAP restart; copy-pasting rules between otel-rules files and forgetting to rename the metric; mixing native meter-analyzer-config rules with otel-rules rules that reuse a metric name.

Related errors


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