Repository navigation
Description
Summary
Muse Spark via OpenCode Go fails on the first request when any tool schema nests deeper than 10 levels. The provider rejects the whole request, not just the offending tool.
Error from provider (Console Go): Upstream request failed: [invalid_request_error] JSON schema exceeds the maximum nesting depth of 10 levels
- Endpoint:
https://opencode.ai/zen/go/v1/responses - Model:
muse-spark-1.3-contributor(provideropencode-go) - Provider response body:
{"model":"muse-spark-1.3-contributor","error":{"param":"parameters","type":"invalid_request_error","message":"Error from provider (Console Go): Upstream request failed: [invalid_request_error] JSON schema exceeds the maximum nesting depth of 10 levels"}} - opencode 1.18.31
Other models on the same provider (for example deepseek-v4.1-flash) accept the same tool schemas, so this only breaks on strictly validating upstreams.
Reproduction
- Enable an MCP server with deep tool schemas. The public Vercel MCP server (
https://mcp.vercel.com) is a minimal example. I measured all 212 publishedinputSchemas by counting object/array member recursion (properties,items,additionalProperties,anyOf,oneOf,allOf,$defs). Twelve reach depth 10 or more:
| tool | depth | bytes | deepest path |
|---|---|---|---|
create_flag |
14 | 10234 | .requestBody.environments.oneOf[0].additionalProperties.rules.items.conditions.items.rhs.anyOf[0].items.items.anyOf[0].label |
update_flag |
13 | 10346 | .requestBody.environments.additionalProperties.rules.items.conditions.items.rhs.anyOf[0].items.items.anyOf[0].label |
update_sandbox |
12 | 14775 | .requestBody.networkPolicy.oneOf[1].allow.oneOf[1].additionalProperties.items.match.queryString.items.key.exact |
update_flag_segment |
12 | 4471 | .requestBody.data.rules.items.conditions.items.rhs.anyOf[0].items.items.anyOf[0].label |
create_sandboxes_v4 |
12 | 17019 | .requestBody.networkPolicy.oneOf[1].allow.oneOf[1].additionalProperties.items.match.queryString.items.key.exact |
create_sandboxes_v3 |
12 | 16836 | .requestBody.networkPolicy.oneOf[1].allow.oneOf[1].additionalProperties.items.match.queryString.items.key.exact |
create_sandboxes_v2 |
12 | 17156 | .requestBody.networkPolicy.oneOf[1].allow.oneOf[1].additionalProperties.items.match.queryString.items.key.exact |
update_session_network_policy |
11 | 10708 | .requestBody.oneOf[1].allow.oneOf[1].additionalProperties.items.match.queryString.items.key.exact |
update_project |
11 | 24296 | .requestBody.trustedSources.anyOf[0].projects.additionalProperties.customAllow.items.to.anyOf[0].slugs.items |
put_firewall_config |
11 | 9543 | .requestBody.rules.items.action.mitigate.rateLimit.anyOf[0].anyOf[0].action.anyOf[0].anyOf[0] |
update_firewall_config |
10 | 19348 | .requestBody.oneOf[0].value.conditionGroup.items.conditions.items.value.anyOf[1].items |
create_connector |
10 | 53316 | .requestBody.anyOf[0].data.anyOf[0].serverConfig.jwks.keys.items.key_ops.items |
- Config:
{
"mcp": {
"vercel": { "type": "remote", "url": "https://mcp.vercel.com", "enabled": true, "oauth": {} }
}
}opencode run -m opencode-go/muse-spark-1.3-contributor "Reply with exactly: ok"fails with the error above.- The same command with
"mcp": {}returnsok. - The same command with only the Vercel MCP enabled fails again, so the MCP server is the trigger.
Cause
packages/opencode/src/provider/transform.ts has per-provider schema sanitizers for OpenAI, Moonshot/Kimi, and Gemini, but nothing Meta/Muse-shaped. MCP tool schemas are forwarded as published, so any MCP server over the limit breaks every Muse Spark session. Meta's Model API rejects both recursive $ref (#45800, #48151) and schemas over its nesting limit.
Ask
Add a Meta/Muse-bound sanitizer that flattens tool schemas under the provider's nesting limit and strips recursive $ref, the same way the other providers are handled.
Workaround
Disable the offending MCP server for Muse Spark. A dedicated agent keeps the server available for other models:
{
"agent": {
"muse": {
"mode": "primary",
"model": "opencode-go/muse-spark-1.3-contributor",
"permission": { "vercel_*": "deny" }
}
}
}Related
- Recursive $ref in postgres tool schemas breaks Meta Muse Spark ("Recursive JSON schemas are not currently supported") #45800 Recursive
$refin postgres tool schemas breaks Meta Muse Spark - Console Go -> Meta: sanitize recursive $ref tool schemas (Codex Desktop codex_app tools hit it too) #48151 Console Go -> Meta: sanitize recursive
$reftool schemas - Moonshot/Kimi K2.6 rejects tool schemas with nesting depth > 10, breaking all tool calls #25495 Moonshot/Kimi K2.6 rejects tool schemas with nesting depth > 10
Activity
argszero commentedon Sep 21, 2026
I'd like to work on this.
This looks like a real gap in the provider-specific sanitizers:
packages/opencode/src/provider/transform.tsalready has per-provider schema passes (sanitizeOpenAISchema, plus the Moonshot and Gemini passes) that drop unsupported keywords, but nothing bounds nesting depth, so one deeply nested MCPinputSchemafails the entire request on a strictly validating upstream instead of just degrading that tool.Plan:
properties/items/additionalProperties/$defs/anyOf/oneOf/allOf, and replacing nodes that exceed the limit with a permissive subschema instead of forwarding the offending tree.packages/opencode/test/provider/transform.test.tsusing a fixture at depth >= 10 (shape modelled on the measured Vercelcreate_flagschema), asserting the emitted schema respects the limit and stays a valid JSON Schema.One question on scope, so the change lands in the shape you prefer: should the depth cap be scoped to the Console Go provider (mirroring the existing
opencode-gospecial cases), or would you rather have a per-provider option underprovider.optionsso any upstream limit can be configured? I will default to the provider-scoped approach unless you say otherwise, and keep the change small and additive.argszero commentedon Sep 21, 2026
Opened #50320 with a Meta/Muse schema pass in
packages/opencode/src/provider/transform.ts.It runs for the
metaprovider and for Muse models on the opencode gateways (opencode,opencode-go), and keeps tool schemas within the nesting limit by dropping the members that would nest past it —properties,items,additionalProperties,anyOf/oneOf/allOf,$defs/definitions— while keeping every other keyword on the node. Depth is counted as in the report: the parameter root is level 0, so the deepest surviving schema is 9 steps below it (10 levels counting the root), matching the tools reported as failing at depth 10.Recursive
$ref(#45800, #48151) is a separate concern and is not touched by this PR.thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊
satyalyadav commentedon Oct 12, 2026
Follow-up per the 2.0 ask: still relevant on v2.0.26, with one nuance.
Repro on 2.0: a local MCP server with a tool schema nested 12 levels deep, model
opencode-go/muse-spark-1.3-contributor, server exposed natively (codemode: false) fails withJSON schema exceeds the maximum nesting depth of 10 levels. With Code Mode at its default (MCP tools exposed through Code Mode), the same setup passes, since the deep schema never reaches Meta.The fix is in flight: #51040 (
fix(ai): keep tool schemas within Meta's limits) adds themetasanitizer for nesting depth and recursive$ref, covering this issue, #45800, and #48151. It is open and currently needs a rebase againstdev. Tracking it there rather than opening a duplicate 2.0 issue.p30arena commentedon Oct 16, 2026
I disabled MCPs, and the issue is gone