apache/skywalking · error · IllegalArgumentException
classLoaderNeighbor must not be null
Error message
classLoaderNeighbor must not be null
What it means
The same pool-aware create overload requires a classLoaderNeighbor: a class already loaded by the per-rule RuleClassLoader. On Java 9+ Javassist's CtClass.toClass(Class) needs a class in the target loader to resolve it, and on Java 8 its classloader is used by the legacy toClass(ClassLoader, ProtectionDomain). A null neighbor therefore cannot be mapped to a defining loader and is rejected immediately.
Source
Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/MeterSystem.java:368
* @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
* deregistration, shared-queue handler removal.</li>
* <li>Cascades through {@link ModelRegistry#remove(Class, StorageManipulationOpt)} to drop every downsampling
* variant's {@code Model} from the registry; listener {@code whenRemoving} fires forView on GitHub (pinned to 102af09b4a)
Solutions
- Compile any helper class into the rule's ClassLoader first and pass that class as the neighbor (mirror the meter-DSL runtime applier)
- If custom classloaders are not needed, use the default-pool overload create(metricsName, functionName, type, dataType)
Example fix
// before
meterSystem.create(name, func, type, Long.class, pool, null);
// after
Class<?> neighbor = ruleClassLoader.compileUnit("Placeholder"); // any class from the rule loader
meterSystem.create(name, func, type, Long.class, pool, neighbor); Defensive patterns
Strategy: validation
Validate before calling
if (classLoaderNeighbor == null) {
classLoaderNeighbor = ruleClassLoader.compileUnit("RuleNeighbor"); // any class in the rule loader
}
meterSystem.create(name, func, type, dataType, pool, classLoaderNeighbor); Prevention
- Always compile a placeholder class into the rule ClassLoader before calling create, mirroring the MAL runtime applier
- Pass the simplest available rule-generated class as neighbor; any class from the target loader suffices
- If you never use custom loaders, call the default-pool overload instead
When it happens
Trigger: Calling the pool-aware create with null for the neighbor argument — e.g. an embedding that generates the neighbor class itself but skips that step, or a test double that returns null from a stubbed rule compiler.
Common situations: Custom integrations that drive MeterSystem directly instead of going through the MAL runtime; refactors where the code that compiled a sample class into the rule loader was reordered so create() runs before the neighbor exists.
Related errors
- pool must not be null
- Function {} can't be found by javaassist.
- {slot} expects a plain integer literal, got '{numText}' (suf
- MeterSystem unavailable for MAL compile of {sourceName}
- Can not locate oap core jar file by path:{}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/4d077b17aceec21e.
Report an issue: GitHub.