{"record":{"id":"55b9b80a4f387963","repo":"rohitg00/ai-engineering-from-scratch","slug":"inputresponses-contain-invalid-roots-or-sampling-r","errorCode":null,"errorMessage":"inputResponses contain invalid roots or sampling results","messagePattern":"inputResponses contain invalid roots or sampling results","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py","lineNumber":420,"sourceCode":"                inputRequests=missing_responses, requestState=state\n            )\n\n        workspace_scope = responses[\"workspace_scope\"]\n        review_sample = responses[\"review_sample\"]\n        elicitation = responses[\"review_goal\"]\n        if not all(\n            isinstance(response, dict)\n            for response in (workspace_scope, review_sample, elicitation)\n        ):\n            raise ValueError(\"inputResponses entries must be objects\")\n        elicitation_content = elicitation.get(\"content\", {})\n        if not isinstance(elicitation_content, dict):\n            raise ValueError(\"review_goal.content must be an object\")\n        roots = workspace_scope.get(\"roots\")\n        sample_content = review_sample.get(\"content\", {})\n        goal = elicitation_content.get(\"goal\")\n        if not isinstance(roots, list) or not isinstance(sample_content, dict):\n            raise ValueError(\"inputResponses contain invalid roots or sampling results\")\n        if elicitation.get(\"action\") != \"accept\" or not isinstance(goal, str):\n            raise ValueError(\"review_goal must be accepted with a string goal\")\n        sample = sample_content.get(\"text\")\n        if not isinstance(sample, str):\n            raise ValueError(\"review_sample must contain text\")\n        summary = {\n            \"goal\": goal,\n            \"rootCount\": len(roots),\n            \"sample\": sample,\n            \"topic\": arguments[\"topic\"],\n        }\n        return self._complete(\n            content=[{\"type\": \"text\", \"text\": json.dumps(summary, sort_keys=True)}],\n            isError=False,\n        )\n\n    @staticmethod\n    def _progress(token: str | int, progress: int, total: int, message: str) -> dict[str, Any]:","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py#L402-L438","documentation":"After the object checks, the server requires workspace_scope.roots to be a list (a roots/list result body) and review_sample.content to be an object (a createMessage result body). A missing 'roots' key yields None, and a bare string/array content fails the dict check.","triggerScenarios":"workspace_scope without a 'roots' key or with roots as an object/None, or a review_sample whose content is raw text or a list instead of an object.","commonSituations":"Client forwards an empty no-roots response as null; a sampling shim returns content as a bare string; fixtures written against an older response shape.","solutions":["Supply roots as a list — an empty list [] is acceptable for an empty workspace","Return the sampling result with content as an object, e.g. {\"content\": {\"type\": \"text\", \"text\": ...}}","Mirror the MCP roots/list and sampling/createMessage response shapes exactly"],"exampleFix":"# before\nworkspace_scope = {}\nreview_sample = {\"content\": \"draft text\"}\n\n# after\nworkspace_scope = {\"roots\": []}\nreview_sample = {\"content\": {\"type\": \"text\", \"text\": \"draft text\"}}","handlingStrategy":"validation","validationCode":"roots = responses[\"workspace_scope\"].get(\"roots\")\nsample_content = responses[\"review_sample\"].get(\"content\", {})\nif not isinstance(roots, list):\n    responses[\"workspace_scope\"][\"roots\"] = []\nif not isinstance(sample_content, dict):\n    raise ValueError(\"sampling content must be an object\")","typeGuard":"def valid_roots_and_sample(scope: object, sample: object) -> bool:\n    return (\n        isinstance(scope, dict) and isinstance(scope.get(\"roots\"), list)\n        and isinstance(sample, dict) and isinstance(sample.get(\"content\", {}), dict)\n    )","tryCatchPattern":null,"preventionTips":["Default missing roots to an empty list, not null","Forward roots/list and createMessage results verbatim","Write fixtures from captured real responses"],"tags":["mcp","roots","sampling","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}