apache/skywalking · error · IllegalArgumentException
Cannot resolve index access on {simpleName} in def variable
Error message
Cannot resolve index access on {simpleName} in def variable chain What it means
AbstractLogRecord.id() always throws UnexpectedException. AbstractLogRecord is the shared column/schema superclass for log records; it has no single natural key, so every concrete subclass (e.g. the default log record built by LogBuilder implementations) must override id() to produce its StorageID. Calling the inherited method means the subclass forgot (or was constructed before being fully populated).
Source
Thrown at oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALDefCodegen.java:345
} else {
prevExpr = "(" + prevExpr + " == null ? null : "
+ prevExpr + "." + getter.getName() + "())";
currentType = returnType;
canBeNull = true;
}
} else {
prevExpr = prevExpr + "." + getter.getName() + "()";
currentType = returnType;
canBeNull = !returnType.isPrimitive();
}
} else if (seg instanceof LALScriptModel.IndexSegment) {
final int index = ((LALScriptModel.IndexSegment) seg).getIndex();
// Try get(int) method (e.g., JsonArray.get(int))
Method getMethod = null;
try {
getMethod = currentType.getMethod("get", int.class);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(
"Cannot resolve index access on "
+ currentType.getSimpleName()
+ " in def variable chain");
}
final Class<?> returnType = getMethod.getReturnType();
if (canBeNull) {
prevExpr = "(" + prevExpr + " == null ? null : "
+ prevExpr + ".get(" + index + "))";
} else {
prevExpr = prevExpr + ".get(" + index + ")";
}
currentType = returnType;
canBeNull = true;
}
}
genCtx.lastResolvedType = currentType;
sb.append(prevExpr);View on GitHub (pinned to 102af09b4a)
Solutions
- Override id() in the concrete record subclass to return a StorageID built from the record's identity columns (e.g. timestamp + serviceId + traceId)
- If using the built-in log storage, return the stock LogRecord implementation rather than your own AbstractLogRecord subclass
- Add an abstract-method-style test that fails when a new AbstractLogRecord subclass lacks id()
Example fix
// before
class MyLogRecord extends AbstractLogRecord { } // inherits throwing id()
// after
class MyLogRecord extends AbstractLogRecord {
@Override
public StorageID id() {
return new StorageID()
.append(TIME_BUCKET, getTimeBucket())
.append(SERVICE_ID, getServiceId());
}
} Defensive patterns
Strategy: type-guard
Type guard
boolean hasId = record.getClass() != AbstractLogRecord.class
&& java.util.stream.Stream.of(record.getClass().getMethods())
.anyMatch(m -> m.getName().equals("id") && m.getDeclaringClass() != AbstractLogRecord.class); Try / catch
try { id = record.id(); } catch (UnexpectedException e) { throw new IllegalStateException(record.getClass() + " must override id()", e); } Prevention
- Always override id() in AbstractLogRecord subclasses
- Prefer reusing the stock LogRecord class from LogBuilder
When it happens
Trigger: An instance whose runtime class does not override id() flows into storage or query code that calls record.id() — e.g. registering a custom LogBuilder that instantiates a bare subclass of AbstractLogRecord without implementing id(), or unit tests instantiating the abstract record directly.
Common situations: Writing a custom LAL sink / log storage implementation that reuses AbstractLogRecord; copy-pasting a record class and dropping the id() override; reflective instantiation of a log record class that was refactored.
Related errors
- Load meter analyzer configs failed
- Failed to load GenAI configuration file.
- Failed to compile hierarchy rule: {name}, expression: {expre
- Hierarchy rule parsing failed: {errors} in expression: {expr
- Output type {outputTypeName} has no setter for field '{field
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/3a20e9bc3d3e9955.
Report an issue: GitHub.