apache/skywalking · error · IllegalArgumentException

pool must not be null

Error message

pool must not be null

What it means

The pool-aware MeterSystem.create(String, String, ScopeType, Class, ClassPool, Class) overload is used by the runtime MAL/LAL rule applier, which builds a fresh ClassPool and a per-file RuleClassLoader for each rule file. It rejects a null pool up front because every subsequent step (resolving the function CtClass, generating and toClass()-ing the Metrics subclass) dereferences it. This is a fail-fast guard against internal API misuse, not a user-config error.

Source

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

     * @param functionName         function provided through {@link MeterFunction}
     * @param type                 scope type
     * @param dataType             accepted value data type
     * @param pool                 per-file Javassist pool, typically constructed as
     *                             {@code new ClassPool(ClassPool.getDefault())} with
     *                             {@code LoaderClassPath(ruleLoader)} appended
     * @param classLoaderNeighbor  a class loaded by the per-file {@code RuleClassLoader}; used
     *                             by Javassist's {@code toClass(Class)} on Java 9+ to resolve
     *                             the target loader. On Java 8, its classloader is passed to
     *                             the legacy {@code toClass(ClassLoader, ProtectionDomain)}
     */
    public synchronized <T> void create(String metricsName,
                                        String functionName,
                                        ScopeType type,
                                        Class<T> dataType,
                                        ClassPool pool,
                                        Class<?> classLoaderNeighbor) throws IllegalArgumentException {
        if (pool == null) {
            throw new IllegalArgumentException("pool must not be null");
        }
        if (classLoaderNeighbor == null) {
            throw new IllegalArgumentException("classLoaderNeighbor must not be null");
        }
        createInternal(metricsName, functionName, type, dataType, pool, classLoaderNeighbor,
            StorageManipulationOpt.withSchemaChange());
    }

    /**
     * Remove a previously-registered metric by name. Symmetric to {@link #create(String, String,
     * ScopeType, Class)} / the pool-aware overload. Used by runtime rule hot-remove (MAL/LAL)
     * to retire a metric class cleanly.
     *
     * <p>Steps:
     * <ol>
     *   <li>Drops the {@link #meterPrototypes} entry so {@link #buildMetrics(String, Class)}
     *       rejects further builds for this name.</li>
     *   <li>Delegates to {@link MetricsStreamProcessor#removeMetric} — L1/L2 drain, worker

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Construct and pass a real pool: ClassPool pool = ClassPool.getDefault(); pool.appendClassPath(...) for the rule's loader — see the runtime applier in oap-server/analyzer for the canonical pattern
  2. If you do not need a custom loader, call the simpler overload create(metricsName, functionName, type, dataType) which uses the default pool

Example fix

// before
meterSystem.create(name, func, type, Long.class, null, neighbor);

// after
ClassPool pool = ClassPool.getDefault();
pool.appendClassPath(new ClassClassPath(functionClass));
meterSystem.create(name, func, type, Long.class, pool, neighbor);
Defensive patterns

Strategy: validation

Validate before calling

ClassPool pool = (pool == null) ? ClassPool.getDefault() : pool;
// or simply reject before calling:
// Objects.requireNonNull(pool, "pool");
meterSystem.create(name, func, type, dataType, pool, neighbor);

Prevention

When it happens

Trigger: Calling the pool-aware create overload with a null ClassPool — typically a custom embedding of MeterSystem, a unit test stubbing the rule applier, or a code path that builds a pool lazily and passes the unassigned field.

Common situations: Third-party code embedding the OAP core MeterSystem outside the standard server-starter; test harnesses that pass null intending the default-pool overload to be selected, but matching the pool overload because of an extra argument; refactors that removed pool construction from a branch.

Related errors


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