pinpoint-apm/pinpoint · error · UnsupportedOperationException
unsupported type:${dataType}
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.
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)
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:${typeCode} data:${o}
- value
- list size not same
- spanEventList is empty.
- first SpanEvent is null
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/e1bb051a00d7ceb0.
Report an issue: GitHub.