Skip to content

Commit d14cacf

Browse files
authored
Fix NPE in Bedrock converseStream when tool use has empty arguments (#18783)
1 parent a7571ea commit d14cacf

3 files changed

Lines changed: 126 additions & 0 deletions

File tree

‎instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/internal/BedrockRuntimeImpl.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,9 @@ private static String serializeDocument(Document document) {
17551755

17561756
private static Document deserializeDocument(String json) {
17571757
JsonNode node = JSON_PARSER.parse(json);
1758+
if (node == null) {
1759+
return Document.mapBuilder().build();
1760+
}
17581761
return node.visit(DOCUMENT_UNMARSHALLER);
17591762
}
17601763

‎instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2BedrockRuntimeTest.java‎

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import static java.util.Collections.singletonList;
2828
import static java.util.stream.Collectors.toList;
2929
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.assertj.core.api.Assertions.assertThatCode;
3031
import static org.assertj.core.api.Assertions.within;
3132

3233
import io.opentelemetry.api.common.AttributeKey;
@@ -667,6 +668,65 @@ void testConverseToolCall() {
667668
+ "The current weather in Seattle is 50 degrees and raining. In San Francisco, the weather is 70 degrees and sunny.")))));
668669
}
669670

671+
@Test
672+
void testConverseStreamToolCallWithEmptyToolArguments() {
673+
BedrockRuntimeAsyncClientBuilder builder = BedrockRuntimeAsyncClient.builder();
674+
builder.overrideConfiguration(createOverrideConfigurationBuilder().build());
675+
configureClient(builder);
676+
BedrockRuntimeAsyncClient client = configureBedrockRuntimeClient(builder.build());
677+
678+
String modelId = "amazon.nova-micro-v1:0";
679+
List<Message> messages = new ArrayList<>();
680+
messages.add(
681+
Message.builder()
682+
.role(ConversationRole.USER)
683+
.content(ContentBlock.fromText("What time is it?"))
684+
.build());
685+
686+
ConverseStreamResponseHandler responseHandler =
687+
ConverseStreamResponseHandler.builder()
688+
.subscriber(ConverseStreamResponseHandler.Visitor.builder().build())
689+
.build();
690+
691+
assertThatCode(
692+
() ->
693+
client
694+
.converseStream(
695+
ConverseStreamRequest.builder()
696+
.modelId(modelId)
697+
.messages(messages)
698+
.toolConfig(serverTimeToolConfig())
699+
.build(),
700+
responseHandler)
701+
.join())
702+
.doesNotThrowAnyException();
703+
704+
getTesting()
705+
.waitAndAssertLogRecords(
706+
log ->
707+
log.hasAttributesSatisfyingExactly(
708+
equalTo(GEN_AI_PROVIDER_NAME, AWS_BEDROCK),
709+
equalTo(EVENT_NAME, "gen_ai.user.message"))
710+
.hasBody(Value.of(KeyValue.of("content", Value.of("What time is it?")))),
711+
log ->
712+
log.hasAttributesSatisfyingExactly(
713+
equalTo(GEN_AI_PROVIDER_NAME, AWS_BEDROCK),
714+
equalTo(EVENT_NAME, "gen_ai.choice"))
715+
.hasBody(
716+
Value.of(
717+
KeyValue.of("finish_reason", Value.of("tool_use")),
718+
KeyValue.of("index", Value.of(0)),
719+
KeyValue.of(
720+
"toolCalls",
721+
Value.of(
722+
Value.of(
723+
KeyValue.of("name", Value.of("get_server_time")),
724+
KeyValue.of("arguments", Value.of("{}")),
725+
KeyValue.of("id", Value.of("tooluse_empty_params_test")),
726+
KeyValue.of("type", Value.of("function"))))),
727+
KeyValue.of("content", Value.of("")))));
728+
}
729+
670730
@Test
671731
void testConverseToolCallStream() {
672732
BedrockRuntimeAsyncClientBuilder builder = BedrockRuntimeAsyncClient.builder();
@@ -1067,6 +1127,27 @@ void testConverseToolCallStream() {
10671127
+ "The current weather in Seattle is 50 degrees and it is raining. In San Francisco, the weather is 70 degrees and sunny.")))));
10681128
}
10691129

1130+
private static ToolConfiguration serverTimeToolConfig() {
1131+
return ToolConfiguration.builder()
1132+
.tools(
1133+
Tool.builder()
1134+
.toolSpec(
1135+
ToolSpecification.builder()
1136+
.name("get_server_time")
1137+
.description("Get the current server time.")
1138+
.inputSchema(
1139+
ToolInputSchema.builder()
1140+
.json(
1141+
Document.mapBuilder()
1142+
.putString("type", "object")
1143+
.putDocument("properties", Document.mapBuilder().build())
1144+
.build())
1145+
.build())
1146+
.build())
1147+
.build())
1148+
.build();
1149+
}
1150+
10701151
private static ToolConfiguration currentWeatherToolConfig() {
10711152
return ToolConfiguration.builder()
10721153
.tools(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
3+
name: model_amazonnova-micro-v10_converse-stream_empty_tool_args
4+
request:
5+
url: /model/amazon.nova-micro-v1%3A0/converse-stream
6+
method: POST
7+
bodyPatterns:
8+
- equalToJson: |-
9+
{
10+
"messages" : [ {
11+
"role" : "user",
12+
"content" : [ {
13+
"text" : "What time is it?"
14+
} ]
15+
} ],
16+
"toolConfig" : {
17+
"tools" : [ {
18+
"toolSpec" : {
19+
"name" : "get_server_time",
20+
"description" : "Get the current server time.",
21+
"inputSchema" : {
22+
"json" : {
23+
"type" : "object",
24+
"properties" : { }
25+
}
26+
}
27+
}
28+
} ]
29+
}
30+
}
31+
ignoreArrayOrder: false
32+
ignoreExtraElements: false
33+
response:
34+
status: 200
35+
base64Body: AAAAnQAAAFLJ0QwQCzpldmVudC10eXBlBwAMbWVzc2FnZVN0YXJ0DTpjb250ZW50LXR5cGUHABBhcHBsaWNhdGlvbi9qc29uDTptZXNzYWdlLXR5cGUHAAVldmVudHsicm9sZSI6ImFzc2lzdGFudCIsInAiOiJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRiJ94fNKfAAAAPwAAABXHemmYgs6ZXZlbnQtdHlwZQcAEWNvbnRlbnRCbG9ja1N0YXJ0DTpjb250ZW50LXR5cGUHABBhcHBsaWNhdGlvbi9qc29uDTptZXNzYWdlLXR5cGUHAAVldmVudHsiY29udGVudEJsb2NrSW5kZXgiOjAsInAiOiJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRiIsInN0YXJ0Ijp7InRvb2xVc2UiOnsibmFtZSI6ImdldF9zZXJ2ZXJfdGltZSIsInRvb2xVc2VJZCI6InRvb2x1c2VfZW1wdHlfcGFyYW1zX3Rlc3QifX19ecyMJQAAAKQAAABWYo0S/gs6ZXZlbnQtdHlwZQcAEGNvbnRlbnRCbG9ja1N0b3ANOmNvbnRlbnQtdHlwZQcAEGFwcGxpY2F0aW9uL2pzb24NOm1lc3NhZ2UtdHlwZQcABWV2ZW50eyJjb250ZW50QmxvY2tJbmRleCI6MCwicCI6ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6QUJDREVGIn07lyU5AAAAlQAAAFFgqBZrCzpldmVudC10eXBlBwALbWVzc2FnZVN0b3ANOmNvbnRlbnQtdHlwZQcAEGFwcGxpY2F0aW9uL2pzb24NOm1lc3NhZ2UtdHlwZQcABWV2ZW50eyJwIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3QiLCJzdG9wUmVhc29uIjoidG9vbF91c2UifUV9XIkAAADgAAAATtySdCELOmV2ZW50LXR5cGUHAAhtZXRhZGF0YQ06Y29udGVudC10eXBlBwAQYXBwbGljYXRpb24vanNvbg06bWVzc2FnZS10eXBlBwAFZXZlbnR7Im1ldHJpY3MiOnsibGF0ZW5jeU1zIjoxMDB9LCJwIjoiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQkNERUYiLCJ1c2FnZSI6eyJpbnB1dFRva2VucyI6NTAsIm91dHB1dFRva2VucyI6MTAsInRvdGFsVG9rZW5zIjo2MH198F6oVg==
36+
headers:
37+
Date: "Mon, 18 May 2026 10:00:00 GMT"
38+
Content-Type: application/vnd.amazon.eventstream
39+
x-amzn-RequestId: test-empty-tool-args-request-id
40+
uuid: a1b2c3d4-e5f6-7890-abcd-ef1234567890
41+
persistent: true
42+
insertionIndex: 100

0 commit comments

Comments
 (0)