apache/skywalking · error · IllegalArgumentException
tag() requires exactly one string literal argument, e.g. tag
Error message
tag() requires exactly one string literal argument, e.g. tag("KEY") What it means
Thrown by MeterSystem.createInternal when the requested function exists but its AcceptableValue generic parameter does not equal the data type passed by the caller (e.g. the function is AcceptableValue<Long> and the creation path supplies Double). The meter framework generates a Javassist subclass binding the function to the metric's data type; mismatched generics cannot be compiled safely, so it fails fast with the expected vs. actual type names.
Source
Thrown at oap-server/analyzer/log-analyzer/src/main/java/org/apache/skywalking/oap/log/analyzer/v2/compiler/LALValueCodegen.java:742
generateBinaryExpression(sb, value.getConcatParts(),
value.getConcatOps(), genCtx);
return;
}
// Handle parenthesized expression: (innerExpr as Type).chain...
if (value.getParenInner() != null) {
generateParenAccess(sb, value, genCtx);
return;
}
// tag("KEY") — reads LogData tags via LalRuntimeHelper.tagValue().
// Only valid when input is LogData.Builder (i.e. no inputType, or inputType
// is LogData.Builder). For typed inputs, tag() is not supported — use
// parsed.* to access fields on the typed input.
if ("tag".equals(value.getFunctionCallName())) {
if (value.getFunctionCallArgs().size() != 1
|| !value.getFunctionCallArgs().get(0).getValue().isStringLiteral()) {
throw new IllegalArgumentException(
"tag() requires exactly one string literal argument, "
+ "e.g. tag(\"KEY\")");
}
if (genCtx.inputType != null
&& !LALCodegenHelper.LOGDATA_BUILDER_CLASS
.isAssignableFrom(genCtx.inputType)) {
throw new IllegalArgumentException(
"tag() reads LogData tags but the input type is "
+ genCtx.inputType.getName()
+ ". Use a json{}/yaml{}/text{} parser, or access "
+ "typed fields via parsed.* instead.");
}
sb.append("h.tagValue(\"");
final String key = value.getFunctionCallArgs().get(0)
.getValue().getSegments().get(0);
sb.append(DslJavaSourceText.toLiteral(key)).append("\")");
return;
}View on GitHub (pinned to 102af09b4a)
Solutions
- Align the data type: pass the type the function declares in AcceptableValue<T> (the error prints both type names)
- Or switch to a function whose generic parameter matches your data type
- Recompile custom functions and callers together so the generic contract stays consistent
Example fix
// before — function declares AcceptableValue<Long>
meterSystem.create("my_metric", "sum", ScopeType.SERVICE);
// custom create path passing Double
class LongSumFunction implements AcceptableValue<Long> { ... }
// after — use a function declaring AcceptableValue<Double>
class DoubleSumFunction implements AcceptableValue<Double> { ... } Defensive patterns
Strategy: type-guard
Validate before calling
for (Type t : functionClass.getGenericInterfaces()) {
if (t instanceof ParameterizedType && ((ParameterizedType) t).getRawType().getTypeName().endsWith("AcceptableValue")) {
Type arg = ((ParameterizedType) t).getActualTypeArguments()[0];
if (!arg.equals(dataType)) throw new IllegalArgumentException("type mismatch: " + arg);
}
} Type guard
static boolean acceptsType(Class<? extends AcceptableValue<?>> fn, Class<?> dataType) {
for (Type t : fn.getGenericInterfaces()) {
if (t instanceof ParameterizedType) {
ParameterizedType p = (ParameterizedType) t;
if (p.getRawType().getTypeName().endsWith("AcceptableValue")) {
return p.getActualTypeArguments()[0].equals(dataType);
}
}
}
return false;
} Prevention
- Keep the AcceptableValue generic parameter of custom functions in sync with the creation call
- The error message names both types — read expected vs actual before changing code
When it happens
Trigger: A custom MeterSystem.create caller passing dataType=Double.class for a function declared AcceptableValue<Long>, or a MAL expression producing a value type inconsistent with the chosen function (e.g. a percent function expecting Long fed by a decimal-producing expression).
Common situations: Writing custom meter functions or direct MeterSystem integrations; changing a function's generic parameter without rebuilding dependent rules; MAL function selection that doesn't match the expression's numeric type.
Related errors
- {slot} value '{numText}' exceeds the supported range (must f
- Unsupported extractor statement in LAL rule at line {sourceL
- {slot} value '{numText}' exceeds the supported range (must f
- Unclosed interpolation in: {s}
- Cannot parse interpolation expression: {expr}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/913b5b47c1162a67.
Report an issue: GitHub.