In arcp-otel/src/main/java/dev/arcp/otel/ArcpOtel.java the injectTraceContext method around line 172 reads ObjectNode ext = (ObjectNode) payload.path("extensions"); on line 179. If the payload has an "extensions" key whose value is not a JSON object — for example a string, array, or null — the cast throws ClassCastException at runtime, taking down the send call (which the TracingTransport wraps with a try/finally that records the exception and rethrows). Any envelope shape that legitimately uses "extensions" as something other than an object (the spec does not mandate object semantics for the field) will break tracing.\n\nThe block of code immediately following the cast is also dead. After if (ext.isMissingNode()) { ext = payload.putObject("extensions"); } runs and creates a fresh object, the subsequent else if (!payload.has("extensions")) can never be true (the path() call against a missing node still leaves payload unchanged but the subsequent has() check is now meaningfully wrong, and even when ext is not missing the else-if branch is unreachable because if path() returned a real node, payload.has("extensions") is by definition true).\n\nThe extractTraceContext method directly below has the same unguarded cast risk on line 201.\n\nFix prompt: In arcp-otel/src/main/java/dev/arcp/otel/ArcpOtel.java rewrite both injectTraceContext and extractTraceContext to type-check payload.path("extensions") against JsonNode.isObject() before casting. If the value exists but is not an object, log a warning at WARN level and return the envelope unchanged (for inject) or Context.current() (for extract) without throwing. Delete the dead else if (!payload.has("extensions")) branch — the only meaningful path is "missing → create new object" or "already an object → reuse." Add JUnit tests in arcp-otel/src/test/java/dev/arcp/otel/ that exercise three cases: extensions absent, extensions present as an object, and extensions present as a string or array. The third must round-trip cleanly without throwing.
In arcp-otel/src/main/java/dev/arcp/otel/ArcpOtel.java the injectTraceContext method around line 172 reads
ObjectNode ext = (ObjectNode) payload.path("extensions");on line 179. If the payload has an "extensions" key whose value is not a JSON object — for example a string, array, or null — the cast throws ClassCastException at runtime, taking down the send call (which the TracingTransport wraps with a try/finally that records the exception and rethrows). Any envelope shape that legitimately uses "extensions" as something other than an object (the spec does not mandate object semantics for the field) will break tracing.\n\nThe block of code immediately following the cast is also dead. Afterif (ext.isMissingNode()) { ext = payload.putObject("extensions"); }runs and creates a fresh object, the subsequentelse if (!payload.has("extensions"))can never be true (the path() call against a missing node still leaves payload unchanged but the subsequent has() check is now meaningfully wrong, and even when ext is not missing the else-if branch is unreachable because if path() returned a real node, payload.has("extensions") is by definition true).\n\nThe extractTraceContext method directly below has the same unguarded cast risk on line 201.\n\nFix prompt: In arcp-otel/src/main/java/dev/arcp/otel/ArcpOtel.java rewrite both injectTraceContext and extractTraceContext to type-checkpayload.path("extensions")against JsonNode.isObject() before casting. If the value exists but is not an object, log a warning at WARN level and return the envelope unchanged (for inject) or Context.current() (for extract) without throwing. Delete the deadelse if (!payload.has("extensions"))branch — the only meaningful path is "missing → create new object" or "already an object → reuse." Add JUnit tests in arcp-otel/src/test/java/dev/arcp/otel/ that exercise three cases: extensions absent, extensions present as an object, and extensions present as a string or array. The third must round-trip cleanly without throwing.