Skip to content

Bug: Zod internal properties leak into JSON Schema sent to provider (Kimi k2.6) #28704

Closed as not planned

Description

@alysson-falcao

Description

When using the Kimi k2.6 model provider, opencode fails with the error:

Error from provider: JSON Schema not supported: could not understand the instance `{'_def': ...}`

The tool schemas sent to the API contain raw Zod internal properties (_def, typeName, ~standard, _cached) instead of standard JSON Schema.

Environment

  • opencode version: v1.0.146 (via context-mode plugin)
  • Model: Kimi k2.6
  • OS: Linux

Root Cause

The ctx_batch_execute (and likely other) MCP tools define their parameters using Zod schemas. When opencode serializes these schemas for the provider API, the Zod internal representation leaks through instead of being converted to clean JSON Schema.
The failing schema excerpt:

{
  "_def": {
    "type": {
      "_def": {
        "unknownKeys": "strip",
        "catchall": {"_def": {"typeName": "ZodNever"}, "~standard": {"version": 1, "vendor": "zod"}},
        "typeName": "ZodObject"
      },
      "~standard": {"version": 1, "vendor": "zod"},
      "_cached": null
    },
    "minLength": {"value": 1},
    "typeName": "ZodArray",
    "description": "Commands to execute as a batch..."
  },
  "~standard": {"version": 1, "vendor": "zod"}
}

Note typeName: "ZodArray", typeName: "ZodObject", _def, ~standard — all Zod internals.
What the provider expects (standard JSON Schema):

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {...}
  },
  "minItems": 1,
  "description": "Commands to execute as a batch..."
}

Likely the conversion uses JSON.parse(JSON.stringify(schema)) or similar shallow serialization that doesn't invoke Zod's toJSON() or zod-to-json-schema properly.

Steps to Reproduce

  1. Run opencode with Kimi k2.6 as the provider
  2. The provider layer attempts to serialize MCP tool schemas to send to the API
  3. Zod internals leak through, Kimi API rejects with "JSON Schema not supported"

Expected Behavior

Tool schemas should be serialized to standard JSON Schema (draft-07 or similar) before being sent to the provider API.

Suggested Fix

When serializing Zod schemas for provider tool definitions, use a proper conversion library like zod-to-json-schema or at minimum strip _def, ~standard, _cached, and typeName internal properties before sending. The serialization should produce output compatible with JSON Schema draft-07.
Workaround candidate for the provider layer:

function sanitizeSchema(schema: unknown): unknown {
  if (schema && typeof schema === 'object' && '_def' in (schema as any)) {
    return sanitizeSchema((schema as any)._def);
  }
  if (Array.isArray(schema)) {
    return schema.map(sanitizeSchema);
  }
  if (schema && typeof schema === 'object') {
    const cleaned: Record<string, unknown> = {};
    for (const [key, value] of Object.entries(schema)) {
      if (key === '_def' || key === '~standard' || key === '_cached') continue;
      cleaned[key] = sanitizeSchema(value);
    }
    return cleaned;
  }
  return schema;
}

Plugins

context-mode

OpenCode version

No response

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

Windows - WSL - Debian

Terminal

No response

Activity

  1. github-actions commented on May 21, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct (e.g., specific to the MCP ctx_batch_execute tool or the Kimi k2.6 provider path rather than the general serialization layer), please add that context to help distinguish it from the above.

  2. Baijack-star commented on May 21, 2026

    @Baijack-star

    I took a quick look at current main to separate this from the older general Zod v3/v4 reports.

    The likely useful split is where the raw Zod object first enters the tool pipeline, not the Kimi provider adapter itself:

    • Built-in opencode tools are converted through packages/opencode/src/tool/json-schema.ts (ToolJsonSchema.fromTool() / Effect Schema.toJsonSchemaDocument).
    • Plugin Zod tools now go through packages/opencode/src/tool/registry.ts via z.toJSONSchema(...) and normalizeZodJsonSchema(...).
    • MCP tools are normalized in packages/opencode/src/session/tools.ts with asSchema(item.inputSchema).jsonSchema, then passed through ProviderTransform.schema(...).
    • packages/opencode/src/provider/transform.ts already has a Kimi/Moonshot sanitizer, but it assumes the input is already JSON Schema. It strips/adjusts $ref siblings and tuple items; it does not and probably should not try to interpret raw Zod internals.

    So I would add the regression/guard one layer earlier: right before jsonSchema(transformed) in session/tools.ts and for plugin tools after registry load, assert that the final schema tree contains none of _def, def, _zod, ~standard, _cached, or typeName. If that guard fails, log the tool name/source (ctx_batch_execute / context-mode) and fail with a local diagnostic before the provider request is built.

    That should answer whether this is still the known Zod conversion bug or a distinct bypass in the context-mode/MCP tool path. For Kimi specifically, a focused failing test would create a synthetic tool with an array-of-object parameter, run it through SessionTools.resolve for providerID: "moonshotai" or a Kimi model id, and assert the final AI SDK tool schema is:

    {
      "type": "array",
      "items": { "type": "object", "properties": {} }
    }

    with no Zod-private keys anywhere in the serialized body.

  3. nibirrayy commented on Jun 1, 2026

    @nibirrayy

    Same issue on my setup — additional context:

    Environment:

    • opencode v1.15.13 (macOS arm64, binary at ~/.opencode/bin/opencode)
    • Model: Kimi K2.6 via OpenCode Go (opencode-go/kimi-k2.6, endpoint https://opencode.ai/zen/go/v1/chat/completions, @ai-sdk/openai-compatible)
    • context-mode v1.0.160 (latest), loaded as both MCP server + plugin ("plugin": ["context-mode"])
    • MCP tools active: context-mode, zai-mcp-server, exa, grep, elevenlabs, context7, web-search-prime, web-reader

    Error:

    Error from provider: JSON Schema not supported: could not understand the instance `{'_def': {'schema': {'_def': {'type': {'_def': {'unknownKeys': 'strip', 'catchall': {'_def': {'typeName': 'ZodNever'}, '~standard': {'version': 1, 'vendor': 'zod'}}, 'typeName': 'ZodObject'}...`
    

    What I've confirmed:

    • The raw Zod v4 internal representation (_def, typeName: "ZodObject", ~standard: {version: 1, vendor: "zod"}) is being sent directly to the OpenCode Go endpoint without conversion to standard JSON Schema
    • This happens for all tool schemas — built-in tools (bash, read, edit, glob, grep, etc.) AND MCP tools AND plugin tools
    • Upgrading context-mode from v1.0.111 → v1.0.160 did not fix it — the issue is in opencode's core schema serialization for the Kimi provider path
    • Other OpenCode Go models that use @ai-sdk/anthropic (MiniMax M2.7, Qwen) work fine — the issue is specific to models routed through @ai-sdk/openai-compatible that have strict JSON Schema validation (Kimi)
    • Other providers (Claude via @ai-sdk/anthropic, GPT, Gemini) work fine

    Config snippet (opencode.json):

    {
      "plugin": ["context-mode"],
      "mcp": {
        "context-mode": {
          "type": "local",
          "command": ["context-mode"]
        }
      }
    }

    Impact: Kimi K2.6 is completely unusable with opencode when any tools are registered via the OpenCode Go endpoint. Would love to see #28997 or #28080 land — happy to test any fixes.

  4. giomartinsdev commented on Jun 5, 2026

    @giomartinsdev

    i have this issue too

  5. github-actions commented on Aug 5, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions