pinpoint-apm/pinpoint · error · UnsupportedOperationException
unsupported type
Error message
unsupported type:${dataType} What it means
AnnotationValueMapper.map converts profiler annotation value objects into protobuf message types for gRPC transport. It dispatches on the runtime type of dataType through an if/else chain of known types; if the type is not one of the supported annotation value classes, it throws UnsupportedOperationException with the value's type name. This protects the wire protocol from unmapped data types.
Solutions
- Use only supported annotation value types (primitives, String, byte[], and the TBytes* typed classes) when recording annotations.
- Convert the custom type into a supported one before Annotation.setAnnotationValue — e.g. serialize the object to byte[]/String.
- Align versions: update the agent so mapper and plugin API versions match.
- Extend AnnotationValueMapper (and the proto) in a fork if a new type must be transported.
Example fix
// before
annotation.setAnnotationValue("MyAnnotation", myCustomObject); // unsupported type
// after
annotation.setAnnotationValue("MyAnnotation", String.valueOf(myCustomObject)); // or serialized byte[] Defensive patterns
Strategy: type-guard
Validate before calling
static final Set<Class<?>> SUPPORTED = Set.of(
String.class, Integer.class, Long.class, Boolean.class, Double.class,
Short.class, Float.class, Byte.class, byte[].class /* plus TBytes* types */);
boolean supported = dataType == null || SUPPORTED.contains(dataType.getClass()); Type guard
static boolean isSupportedAnnotationValue(Object v) {
return v == null || v instanceof String || v instanceof Number
|| v instanceof Boolean || v instanceof byte[]
|| v instanceof TIntStringStringValue || v instanceof TLongBytesStringStringValue
|| v instanceof TBytesStringStringValue; // extend with all supported types
} Try / catch
try {
PAnnotationValue p = AnnotationValueMapper.map(dataType);
} catch (UnsupportedOperationException e) {
logger.warn("Dropping unsupported annotation value type: {}", e.getMessage());
// omit annotation value or map to String.valueOf(dataType)
} Prevention
- Only record annotations with documented supported value types.
- In custom plugins, serialize complex objects to String/byte[] before Annotation.setAnnotationValue.
- Keep plugin API and agent versions aligned to avoid unmapped newer types.
When it happens
Trigger: Recording an annotation whose value object's class is not in the mapper's supported set (e.g. a new/custom annotation value type, or a type added in a newer Pinpoint core than the mapper supports) and then sending the span to the collector via gRPC.
Common situations: Custom plugins adding their own annotation value types; mixing Pinpoint component versions (agent plugin compiled against newer API than mapper); annotation APIs producing types the gRPC mapper was never extended for.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- unsupported DataType
- absolute start/end time is only supported for TRACE_V3 span…
- first SpanEvent is null
- Illegal report period:
- invalid metadata serviceUid
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/e1bb051a00d7ceb0.
Report an issue: GitHub.
Appendix: source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/context/grpc/mapper/AnnotationValueMapper.java:206
builder.setIntStringStringValue(pIntStringStringValue);
return builder.build();
} else if (dataType instanceof LongIntIntByteByteStringValue) {
final LongIntIntByteByteStringValue v = (LongIntIntByteByteStringValue) dataType;
final PLongIntIntByteByteStringValue pValue = map(v);
builder.setLongIntIntByteByteStringValue(pValue);
return builder.build();
} else if (dataType instanceof IntBooleanIntBooleanValue) {
final IntBooleanIntBooleanValue v = (IntBooleanIntBooleanValue) dataType;
final PIntBooleanIntBooleanValue pValue = map(v);
builder.setIntBooleanIntBooleanValue(pValue);
return builder.build();
} else if (dataType instanceof BytesStringStringValue) {
final BytesStringStringValue v = (BytesStringStringValue) dataType;
PBytesStringStringValue pValue = map(v);
builder.setBytesStringStringValue(pValue);
return builder.build();
}
throw new UnsupportedOperationException("unsupported type:" + dataType);
}
@InheritConfiguration(name = "dummyForIgnoreMapping")
PIntStringValue map(IntStringValue v);
@InheritConfiguration(name = "dummyForIgnoreMapping")
PStringStringValue map(StringStringValue v);
@InheritConfiguration(name = "dummyForIgnoreMapping")
PIntStringStringValue map(IntStringStringValue v);
@InheritConfiguration(name = "dummyForIgnoreMapping")
@Mapping(source = "intValue2", target = "intValue2", conditionQualifiedByName = "isNotMinusInt")
@Mapping(source = "byteValue1", target = "byteValue1", conditionQualifiedByName = "isNotMinusByte")
@Mapping(source = "byteValue2", target = "byteValue2", conditionQualifiedByName = "isNotMinusByte")
PLongIntIntByteByteStringValue map(LongIntIntByteByteStringValue v);
View on GitHub (pinned to 744c3d3075)