{"record":{"id":"2ae4850af7cb0735","repo":"Hmbown/CodeWhale","slug":"kimi-native-web-search-exceeded-the-max-native-search-tool","errorCode":null,"errorMessage":"Kimi native web search exceeded the {MAX_NATIVE_SEARCH_TOOL_CALLS}-call safety limit","messagePattern":"Kimi native web search exceeded the (.+?)-call safety limit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/client/provider_native_search/kimi.rs","lineNumber":220,"sourceCode":"                )\n                .await?;\n            messages.push(json!({\n                \"role\": \"tool\",\n                \"tool_call_id\": id,\n                \"content\": formula_fiber_result(&fiber)?,\n            }));\n        }\n    }\n\n    bail!(\"Kimi Formula web search exceeded the bounded tool-call loop\")\n}\n\nfn reserve_native_search_tool_calls(executed: &mut usize, additional: usize) -> Result<()> {\n    let total = executed\n        .checked_add(additional)\n        .context(\"Kimi native web search tool-call count overflowed\")?;\n    if total > MAX_NATIVE_SEARCH_TOOL_CALLS {\n        bail!(\n            \"Kimi native web search exceeded the {MAX_NATIVE_SEARCH_TOOL_CALLS}-call safety limit\"\n        );\n    }\n    *executed = total;\n    Ok(())\n}\n\nfn formula_web_search_tools(payload: &Value) -> Result<Value> {\n    let tools = payload\n        .get(\"tools\")\n        .and_then(Value::as_array)\n        .context(\"Kimi web-search Formula omitted tools\")?;\n    if tools.len() != 1\n        || tools[0].get(\"type\").and_then(Value::as_str) != Some(\"function\")\n        || tools[0].pointer(\"/function/name\").and_then(Value::as_str)\n            != Some(WEB_SEARCH_FORMULA_FUNCTION)\n    {\n        bail!(\"Kimi web-search Formula returned an unexpected tool declaration\");","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/client/provider_native_search/kimi.rs#L202-L238","documentation":"All Kimi web-search variants share a hard safety cap: at most MAX_NATIVE_SEARCH_TOOL_CALLS (8) tool calls per search request, counted across all rounds, not per round. reserve_native_search_tool_calls adds the round's call count to the running total (checked_add guards overflow) and bails if the total would exceed the cap.","triggerScenarios":"search_builtin or search_formula reserves a round whose call count pushes the cumulative total above 8; also exercised directly by test native_search_tool_call_limit_is_total_not_per_round.","commonSituations":"A model issuing many parallel searches in one round (e.g. two rounds of 5 calls = 10 > 8); very search-hungry queries; a mistaken assumption that the limit resets per round.","solutions":["Reduce query breadth so fewer total searches are needed","Raise MAX_NATIVE_SEARCH_TOOL_CALLS to accommodate multi-round workloads","Restructure the task into multiple smaller search requests","Accept the failure and fall back to non-native search"],"exampleFix":"// before\nconst MAX_NATIVE_SEARCH_TOOL_CALLS: usize = 8;\n// after\nconst MAX_NATIVE_SEARCH_TOOL_CALLS: usize = 12; // allow 2 rounds of 6 parallel searches","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match provider.search(req).await {\n    Err(e) if e.to_string().contains(\"-call safety limit\") => {\n        warn!(\"Kimi search hit the 8-call cap; reducing parallel searches\");\n        provider.search(req.with_fewer_rounds()).await\n    }\n    other => other,\n}","preventionTips":["Remember the cap is cumulative across rounds, not per round","Keep each round's parallel tool-call count small (<= 8 total)","Raise the constant deliberately with cost/latency review"],"tags":["kimi","web-search","rate-limit","safety-cap"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}