Strict JSON Schema validation fail on backends like SGLang (Missing required field in empty tool parameters) #5251

Open
opened 2026-02-16 17:50:29 -05:00 by yindo · 0 comments
Owner

Originally created by @qingqiuhe on GitHub (Jan 13, 2026).

Originally assigned to: @thdxr on GitHub.

Description

Description

When using opencode with backends that perform strict JSON Schema validation (such as SGLang or other Pydantic-based LLM servers), tool calls for built-in tools with empty parameters (e.g., todoread) fail during the initial request.
The server returns a 400 Bad Request or a validation error similar to:
Tool function has invalid 'parameters' schema: None is not of type 'array' on schema['required']

Root Cause Analysis

The issue stems from how zod schemas are converted to JSON Schema for the LLM provider.
In packages/opencode/src/tool/todo.ts, the todoread tool defines its parameters as an empty object:

export const TodoReadTool = Tool.define("todoread", {
  description: "Use this tool to read your todo list",
  parameters: z.object({}), // This results in a schema without a 'required' field
  // ...
})

In packages/opencode/src/session/prompt.ts, the schema is generated using z.toJSONSchema(item.parameters). For an empty object, it produces:

"parameters": {
  "type": "object",
  "properties": {}
}

Strict validators like SGLang's internal pydantic models fail because they expect "required": [] to be explicitly present if the schema is of type object.

Suggested Fix

The most robust place to fix this is in the provider transformation layer to ensure all object-based schemas satisfy strict requirements.
File: packages/opencode/src/provider/transform.ts

export function schema(model: Provider.Model, schema: any) {
  // ... existing logic ...
  // Ensure 'required' is always an array for object types to satisfy strict backends
  if (schema.type === 'object' && !schema.required) {
    schema.required = [];
  }
  return schema;
}

Environment

  • Opencode Version: 1.1.14
  • LLM Backend: SGLang (v1/chat/completions)
  • Platform: macOS / Linux

Plugins

No response

OpenCode version

1.1.14

Steps to reproduce

  1. Configure opencode to use an SGLang backend (or any backend using strict JSON Schema validation).
  2. Start a session where built-in tools are enabled.
  3. Observe the v1/chat/completions request failing because the backend rejects the todoread tool definition.

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Originally created by @qingqiuhe on GitHub (Jan 13, 2026). Originally assigned to: @thdxr on GitHub. ### Description ### Description When using `opencode` with backends that perform strict JSON Schema validation (such as **SGLang** or other Pydantic-based LLM servers), tool calls for built-in tools with empty parameters (e.g., `todoread`) fail during the initial request. The server returns a `400 Bad Request` or a validation error similar to: `Tool function has invalid 'parameters' schema: None is not of type 'array' on schema['required']` ### Root Cause Analysis The issue stems from how `zod` schemas are converted to JSON Schema for the LLM provider. In `packages/opencode/src/tool/todo.ts`, the `todoread` tool defines its parameters as an empty object: ```typescript export const TodoReadTool = Tool.define("todoread", { description: "Use this tool to read your todo list", parameters: z.object({}), // This results in a schema without a 'required' field // ... }) ``` In `packages/opencode/src/session/prompt.ts`, the schema is generated using `z.toJSONSchema(item.parameters)`. For an empty object, it produces: ```json "parameters": { "type": "object", "properties": {} } ``` Strict validators like SGLang's internal `pydantic` models fail because they expect `"required": []` to be explicitly present if the schema is of type `object`. ### Suggested Fix The most robust place to fix this is in the provider transformation layer to ensure all object-based schemas satisfy strict requirements. **File:** `packages/opencode/src/provider/transform.ts` ```typescript export function schema(model: Provider.Model, schema: any) { // ... existing logic ... // Ensure 'required' is always an array for object types to satisfy strict backends if (schema.type === 'object' && !schema.required) { schema.required = []; } return schema; } ``` ### Environment - **Opencode Version**: 1.1.14 - **LLM Backend**: SGLang (v1/chat/completions) - **Platform**: macOS / Linux ### Plugins _No response_ ### OpenCode version 1.1.14 ### Steps to reproduce 1. Configure `opencode` to use an **SGLang** backend (or any backend using strict JSON Schema validation). 2. Start a session where built-in tools are enabled. 3. Observe the `v1/chat/completions` request failing because the backend rejects the `todoread` tool definition. ### Screenshot and/or share link _No response_ ### Operating System _No response_ ### Terminal _No response_
yindo added the bug label 2026-02-16 17:50:29 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#5251