Skip to content

Commit 0f22862

Browse files
committed
fix(inference): reject a reply whose only message field is null
`hasValidChatMessageFields` set `recognizedField` on the mere presence of a `content`, `reasoning_content`, or `refusal` key, before the value was read. `isValidChatContent` admits `null` because that is the shape OpenAI uses for a pure tool call, so `{"choices":[{"message":{"role":"assistant","content":null}}]}` satisfied the validator with no tool call anywhere in the message. `doctor` and `status` reported "model-invocation probe succeeded" for a reply that carried nothing, which is the shape a quota-exhausted or truncated hosted turn returns. The same function already rejects the message when the key is absent, and its own failure text states the rule it means to enforce: "no choice carried a message with text content, a refusal, or tool calls". A nulled key carries exactly as much proof as a missing one. The flag now moves behind the value check, matching the rule the `tool_calls` branch adopted in NVIDIA#9124: presence claims nothing, only a value does. A reply that pairs `"content": null` with a real tool call still validates, because the `tool_calls` branch sets the flag. Signed-off-by: Udaya Tejas <udayatejas2004@gmail.com>
1 parent 7d516f2 commit 0f22862

2 files changed

Lines changed: 2 additions & 1 deletion

File tree

src/lib/inference/health.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ describe("inference health", () => {
294294
'{"choices":[{"message":{"content":"OK","tool_calls":"none"}}]}',
295295
],
296296
["numeric streaming delta", 'data: {"choices":[{"delta":{"content":123}}]}\n'],
297+
["a null content field and no tool call", '{"choices":[{"message":{"content":null}}]}'],
297298
])("rejects a Chat Completions response with %s", (_description, body) => {
298299
const result = probeRemoteProviderHealth("openai-api", {
299300
model: "gpt-4o-mini",

src/lib/inference/health.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,11 +218,11 @@ function hasValidChatMessageFields(
218218
let recognizedField = false;
219219
for (const field of ["content", "reasoning_content", "refusal"] as const) {
220220
if (!(field in message)) continue;
221-
recognizedField = true;
222221
const value = message[field];
223222
const valid =
224223
field === "content" ? isValidChatContent(value) : value === null || typeof value === "string";
225224
if (!valid) return false;
225+
if (value !== null) recognizedField = true;
226226
}
227227
if ("tool_calls" in message) {
228228
const toolCalls = message.tool_calls;

0 commit comments

Comments
 (0)