{"record":{"id":"07c58a86649fc60d","repo":"xai-org/grok-build","slug":"client-returned-an-invalid-response-to-user-questi","errorCode":null,"errorMessage":"Client returned an invalid response to user question: {msg}","messagePattern":"Client returned an invalid response to user question: (.+?)","errorType":"error_code","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-tools/src/implementations/grok_build/ask_user_question/mod.rs","lineNumber":527,"sourceCode":"            Ok(UserQuestionResponse::SkipInterview {\n                questions,\n                partial_answers,\n            }) => {\n                let message = format::format_skip_interview(&questions, &partial_answers);\n                Ok(AskUserQuestionOutput::UserAnswered { message })\n            }\n            Ok(UserQuestionResponse::Cancelled) => Ok(AskUserQuestionOutput::UserAnswered {\n                message: unanswered.to_string(),\n            }),\n            Err(UserQuestionError::TransportError(msg)) => {\n                Err(xai_tool_runtime::ToolError::execution(\n                    xai_tool_protocol::ToolId::new(\"ask_user_question\").expect(\"valid\"),\n                    format!(\"Failed to reach the client for user question: {msg}\"),\n                ))\n            }\n            Err(UserQuestionError::MalformedResponse(msg)) => {\n                Err(xai_tool_runtime::ToolError::execution(\n                    xai_tool_protocol::ToolId::new(\"ask_user_question\").expect(\"valid\"),\n                    format!(\"Client returned an invalid response to user question: {msg}\"),\n                ))\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::resources::Resources;\n    use crate::types::tool_metadata::test_ctx_with_call_id;\n    use indexmap::IndexMap;\n    use tokio::sync::mpsc;\n\n    fn make_question(question: &str, labels: &[&str]) -> Question {\n        Question {\n            question: question.to_string(),","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-tools/src/implementations/grok_build/ask_user_question/mod.rs#L509-L545","documentation":"After the client answers a user question, the response is deserialized into `UserQuestionResponse`. `UserQuestionError::MalformedResponse(msg)` means the payload arrived but failed to parse or validate (missing fields, wrong shape, unknown variants), and the tool converts it into this execution error. It signals a contract mismatch between client and server response schemas.","triggerScenarios":"The client sends a reply that does not deserialize into `UserQuestionResponse` — e.g. answers keyed incorrectly, annotations of the wrong type, an unrecognized response variant, or a truncated/null body from a buggy or outdated client.","commonSituations":"Custom or third-party ACP clients that implement the user-question extension with an outdated/incorrect schema; version skew after a protocol change (e.g. id-keyed answer format added); middleware/proxies rewriting JSON bodies.","solutions":["Read `{msg}` for the exact serde/deserialization failure and compare the client's response payload against the expected `UserQuestionResponse` schema.","Upgrade or fix the client so its reply matches the current schema (accepted answers + annotations, ChatAboutThis, SkipInterview, or Cancelled).","Check for version skew between agent and client after a protocol update; align both to the same version.","Capture and log the raw response body on the client side to confirm what is actually being sent."],"exampleFix":"// before: client sends legacy shape\n{ \"answer\": \"yes\" }\n// after: client must send the accepted response shape\n{ \"type\": \"accepted\", \"answers\": { \"q1\": \"yes\" }, \"annotations\": {} }","handlingStrategy":"type-guard","validationCode":"// validate the client's reply shape before trusting it\nfunction looksLikeUserQuestionResponse(v) {\n  return v != null && typeof v === \"object\" &&\n    [\"accepted\", \"chat_about_this\", \"skip_interview\", \"cancelled\"].includes(v.type);\n}","typeGuard":"fn is_valid_response(v: &serde_json::Value) -> bool {\n    serde_json::from_value::<UserQuestionResponse>(v.clone()).is_ok()\n}","tryCatchPattern":"try {\n  const out = await tool(\"ask_user_question\", { questions });\n} catch (e) {\n  if (String(e.message).startsWith(\"Client returned an invalid response\")) {\n    logRawClientReply(); // capture payload for schema debugging\n  } else { throw e; }\n}","preventionTips":["Keep client and server protocol versions in lockstep","Generate client response types from the shared schema","Log raw client replies when deserialization fails","Add conformance tests for the user-question response format"],"tags":["schema-mismatch","deserialization","serde","client-response"],"backgroundTag":"malformed-response","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}