xai-org/grok-build · error
-32601
-32601
Error message
Method not found: {other} What it means
The headless ext-method responder (reply_headless_ext_method) answers known interaction methods (x.ai/ask_user_question, x.ai/exit_plan_mode, x.ai/mcp/elicit) with policy replies; any other method gets this JSON-RPC -32601 Method not found error on the response channel. This keeps headless runs from failing the whole turn when the UI is absent.
Source
Thrown at crates/codegen/xai-grok-pager/src/headless/ext_protocol.rs:37
pub(crate) fn reply_headless_ext_method(args: AcpArgsBox<acp::ExtRequest>) {
use xai_grok_tools::implementations::grok_build::ask_user_question::AskUserQuestionExtResponse;
use xai_grok_tools::implementations::grok_build::exit_plan_mode::ExitPlanModeExtResponse;
let method = args.request.method.as_ref();
// Known methods are answered without parsing params: even a malformed request gets the policy reply rather than a dropped channel
let response = match method {
// The model sees the tool's NO_OPERATOR_TEXT (headless sessions are non-interactive), not the interactive "user declined" cancel text
"x.ai/ask_user_question" => ext_response_from(&AskUserQuestionExtResponse::Cancelled),
"x.ai/mcp/elicit" => {
use xai_grok_tools::mcp_elicitation::McpElicitExtResponse;
ext_response_from(&McpElicitExtResponse::Cancel)
}
// The model sees "Your plan has been approved. You can now start coding.".
"x.ai/exit_plan_mode" => ext_response_from(&ExitPlanModeExtResponse {
outcome: "approved".to_string(),
feedback: None,
}),
other => Err(acp::Error::new(
-32601,
format!("Method not found: {other}"),
)),
};
args.response_tx.send(response).ok();
}
/// Coerce a numeric `task_id` (version skew) to a string so it does not fail the decode and leak an untracked background task.
fn de_task_id<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::Deserialize;
match serde_json::Value::deserialize(deserializer)? {
serde_json::Value::String(s) => Ok(s),
serde_json::Value::Number(n) => Ok(n.to_string()),
other => Err(serde::de::Error::custom(format!(
"task_id must be a JSON string or number, got {other}"View on GitHub (pinned to bc7f02eddd)
Solutions
- Confirm the method name matches one supported headless (ask_user_question, exit_plan_mode, mcp/elicit)
- Update reply_headless_ext_method with a policy reply for the new method if you own the code
- Run the client in interactive mode when the method requires a UI
- Check client/server version alignment
Example fix
// before
other => Err(acp::Error::new(-32601, format!("Method not found: {other}")))
// after
"x.ai/mcp/elicit" => ext_response_from(&McpElicitExtResponse::default()),
other => Err(acp::Error::new(-32601, format!("Method not found: {other}"))) Defensive patterns
Strategy: try-catch
Validate before calling
const HEADLESS_SUPPORTED = ["x.ai/ask_user_question", "x.ai/exit_plan_mode", "x.ai/mcp/elicit"];
if (!HEADLESS_SUPPORTED.includes(method)) console.warn(`${method} has no headless policy`); Try / catch
match response {
Err(e) if e.code == -32601 => eprintln!("headless mode does not support: {}", e.message),
Ok(resp) => use(resp),
} Prevention
- When adding a new x.ai/* ext method, add a headless policy reply in the same PR
- Prefer interactive mode for UI-dependent methods
- Keep a capability handshake between client and headless runner
When it happens
Trigger: A reverse ext_method request arrives during a headless run with a method string not in the headless responder's match list — typos, version drift, or a new interactive-only method not yet given a headless policy.
Common situations: Server emitting a newly added x.ai/* ext method while the headless protocol layer hasn't been updated; client invoking interactive methods in headless mode.
Related errors
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/9791cb3d35f57811.
Report an issue: GitHub.