Skip to content

Complex attribute export exception #16705

@cleverchuk

Description

@cleverchuk

Describe the bug

Adding a complex attribute as spanBuilder.setAttribute(valueKey("one"), Value.of(1)) results in below exception stacktrace

[otel.javaagent 2026-03-18 16:33:55:508 -0400] [BatchSpanProcessor_WorkerThread-1] WARN io.opentelemetry.sdk.trace.export.BatchSpanProcessor - Exporter threw an Exception
java.lang.ClassCastException: class io.opentelemetry.api.common.ValueLong cannot be cast to class io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.Value (io.opentelemetry.api.common.ValueLong is in unnamed module of loader 'app'; io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.Value is in unnamed module of loader 'bootstrap')
	at io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler$ValueStatelessMarshaler.getBinarySerializedSize(AttributeKeyValueStatelessMarshaler.java:105)
	at io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler$ValueStatelessMarshaler.getBinarySerializedSize(AttributeKeyValueStatelessMarshaler.java:72)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeMessageWithContext(StatelessMarshalerUtil.java:294)
	at io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler.getBinarySerializedSize(AttributeKeyValueStatelessMarshaler.java:66)
	at io.opentelemetry.exporter.internal.otlp.AttributeKeyValueStatelessMarshaler.getBinarySerializedSize(AttributeKeyValueStatelessMarshaler.java:28)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil$RepeatedElementPairSizeCalculator.accept(StatelessMarshalerUtil.java:262)
	at java.base/java.util.HashMap.forEach(HashMap.java:1430)
	at io.opentelemetry.sdk.common.internal.AttributesMap.forEach(AttributesMap.java:109)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:209)
	at io.opentelemetry.exporter.internal.otlp.traces.SpanStatelessMarshaler.getBinarySerializedSize(SpanStatelessMarshaler.java:93)
	at io.opentelemetry.exporter.internal.otlp.traces.SpanStatelessMarshaler.getBinarySerializedSize(SpanStatelessMarshaler.java:22)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:134)
	at io.opentelemetry.exporter.internal.otlp.traces.InstrumentationScopeSpansStatelessMarshaler.getBinarySerializedSize(InstrumentationScopeSpansStatelessMarshaler.java:57)
	at io.opentelemetry.exporter.internal.otlp.traces.InstrumentationScopeSpansStatelessMarshaler.getBinarySerializedSize(InstrumentationScopeSpansStatelessMarshaler.java:21)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil$RepeatedElementPairSizeCalculator.accept(StatelessMarshalerUtil.java:262)
	at java.base/java.util.IdentityHashMap.forEach(IdentityHashMap.java:1376)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:187)
	at io.opentelemetry.exporter.internal.otlp.traces.ResourceSpansStatelessMarshaler.getBinarySerializedSize(ResourceSpansStatelessMarshaler.java:69)
	at io.opentelemetry.exporter.internal.otlp.traces.ResourceSpansStatelessMarshaler.getBinarySerializedSize(ResourceSpansStatelessMarshaler.java:28)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil$RepeatedElementPairSizeCalculator.accept(StatelessMarshalerUtil.java:262)
	at java.base/java.util.IdentityHashMap.forEach(IdentityHashMap.java:1376)
	at io.opentelemetry.exporter.internal.marshal.StatelessMarshalerUtil.sizeRepeatedMessageWithContext(StatelessMarshalerUtil.java:187)
	at io.opentelemetry.exporter.internal.otlp.traces.LowAllocationTraceRequestMarshaler.calculateSize(LowAllocationTraceRequestMarshaler.java:84)
	at io.opentelemetry.exporter.internal.otlp.traces.LowAllocationTraceRequestMarshaler.initialize(LowAllocationTraceRequestMarshaler.java:57)
	at io.opentelemetry.exporter.internal.otlp.traces.SpanReusableDataMarshaler.export(SpanReusableDataMarshaler.java:46)
	at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter.export(OtlpGrpcSpanExporter.java:73)
	at io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.exportCurrentBatch(BatchSpanProcessor.java:320)
	at io.opentelemetry.sdk.trace.export.BatchSpanProcessor$Worker.run(BatchSpanProcessor.java:233)
	at java.base/java.lang.Thread.run(Thread.java:1474)

This happens with any of the Value.of() api. Are these values only expected to be set by instrumentation and not from application code?

Steps to reproduce

Add below code to an app instrumented with the agent

val span = GlobalOpenTelemetry.get().getTracer("my-scope")
            .spanBuilder("my-span")
            .setAttribute(valueKey("one"), Value.of(1))
            .startSpan()

span.end()

Expected behavior

No exception and spans exported

Actual behavior

Exception and span not exported

Javaagent or library instrumentation version

v2.25.0

Environment

JDK: 25
OS: 24.6.0 Darwin Kernel Version 24.6.0

Additional context

No response

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingneeds triageNew issue that requires triage

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions