{"record":{"id":"9e45662cfeb2b537","repo":"xai-org/grok-build","slug":"32602-9e4566","errorCode":"-32602","errorMessage":"Cannot switch to model '{}': it requires agent '{}' but the active agent is '{}'. Start a new session to use this model.","messagePattern":"Cannot switch to model '(.+?)': it requires agent '(.+?)' but the active agent is '(.+?)'\\. Start a new session to use this model\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-shell/src/agent/config.rs","lineNumber":5527,"sourceCode":"    pub code: String,\n    /// The agent type currently active in the session.\n    pub active_agent_type: String,\n    /// The agent type required by the target model.\n    pub required_agent_type: String,\n    /// The model ID that was requested.\n    pub model_id: String,\n    /// Remediation hint for the client.\n    pub suggestion: String,\n}\nimpl ModelSwitchIncompatibleAgentError {\n    /// Build an `acp::Error` with this structured payload.\n    pub(crate) fn into_acp_error(self) -> acp::Error {\n        let message = format!(\n            \"Cannot switch to model '{}': it requires agent '{}' but the active agent is '{}'. \\\n             Start a new session to use this model.\",\n            self.model_id, self.required_agent_type, self.active_agent_type,\n        );\n        acp::Error::new(acp::ErrorCode::InvalidRequest.into(), message)\n            .data(serde_json::to_value(&self).ok())\n    }\n    /// Try to parse from an `acp::Error.data` field.\n    pub fn from_acp_error(err: &acp::Error) -> Option<Self> {\n        let data = err.data.as_ref()?;\n        let code = data.get(\"code\")?.as_str()?;\n        if code != MODEL_SWITCH_INCOMPATIBLE_AGENT {\n            return None;\n        }\n        serde_json::from_value(data.clone()).ok()\n    }\n    /// Render a user-friendly error message for the TUI.\n    pub fn user_message(&self) -> String {\n        format!(\n            \"Cannot switch to '{}' — it requires agent '{}' but the active agent is '{}'. \\\n             Start /new to use this model.\",\n            self.model_id, self.required_agent_type, self.active_agent_type,\n        )","sourceCodeStart":5509,"sourceCodeEnd":5545,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-shell/src/agent/config.rs#L5509-L5545","documentation":"This is an ACP (agent client protocol) error surfaced as JSON-RPC -32602 (InvalidRequest). The user attempted to switch the session's model, but the requested model is bound to a different agent type than the one currently active in the session. Since an agent type cannot be changed mid-session, the caller must start a new session; the error carries structured `data` (model_id, required_agent_type, active_agent_type) that clients can parse via `from_acp_error`.","triggerScenarios":"Calling the model-switch / `session/set_model` style request with a `model_id` whose required agent type differs from the session's active agent type.","commonSituations":"Picking a model from a global model list without noticing it belongs to another agent (e.g. a plan/agent-specific model); a client UI persisting a previously selected model that was tied to another agent; resuming a session and switching models across agent kinds.","solutions":["Start a new session with the required agent type, then select the model","Choose a different model that is compatible with the currently active agent type","Parse `err.data` with `from_acp_error` to show the user which agent the model requires and which is active","Fix client-side model pickers to filter models by the active agent type"],"exampleFix":"// before\nclient.set_model(session_id, \"grok-plan-only-model\") // requires agent 'planner', active 'coder'\n// after\nlet new_session = client.new_session_with_agent(\"planner\")?;\nclient.set_model(new_session.id, \"grok-plan-only-model\")?","handlingStrategy":"try-catch","validationCode":"// before switching, check the model's agent compatibility via from_acp_error data on failure,\n// or track model -> required_agent mapping client-side and filter the picker:\nlet compatible = models.iter().filter(|m| m.required_agent == active_agent);","typeGuard":"fn is_agent_mismatch(err: &acp::Error) -> bool {\n    err.code == acp::ErrorCode::InvalidRequest.into()\n        && err.message.contains(\"requires agent\")\n        && ModelSwitchError::from_acp_error(err).is_some()\n}","tryCatchPattern":"match client.set_model(session_id, &model_id).await {\n    Err(err) if is_agent_mismatch(&err) => {\n        let info = ModelSwitchError::from_acp_error(&err).unwrap();\n        prompt_new_session(&info.required_agent_type);\n    }\n    other => other,\n}","preventionTips":["Filter model pickers by the active agent type","Do not persist cross-agent model selections across sessions","Surface the structured error data (model_id, required/active agent) in the UI"],"tags":["acp","json-rpc","model-switch","agent","invalid-request"],"backgroundTag":"agent-model-mismatch","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}