rohitg00/ai-engineering-from-scratch · error · ValueError
inputResponses contain invalid roots or sampling results
Error message
inputResponses contain invalid roots or sampling results
What it means
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.
Source
Thrown at certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py:420
inputRequests=missing_responses, requestState=state
)
workspace_scope = responses["workspace_scope"]
review_sample = responses["review_sample"]
elicitation = responses["review_goal"]
if not all(
isinstance(response, dict)
for response in (workspace_scope, review_sample, elicitation)
):
raise ValueError("inputResponses entries must be objects")
elicitation_content = elicitation.get("content", {})
if not isinstance(elicitation_content, dict):
raise ValueError("review_goal.content must be an object")
roots = workspace_scope.get("roots")
sample_content = review_sample.get("content", {})
goal = elicitation_content.get("goal")
if not isinstance(roots, list) or not isinstance(sample_content, dict):
raise ValueError("inputResponses contain invalid roots or sampling results")
if elicitation.get("action") != "accept" or not isinstance(goal, str):
raise ValueError("review_goal must be accepted with a string goal")
sample = sample_content.get("text")
if not isinstance(sample, str):
raise ValueError("review_sample must contain text")
summary = {
"goal": goal,
"rootCount": len(roots),
"sample": sample,
"topic": arguments["topic"],
}
return self._complete(
content=[{"type": "text", "text": json.dumps(summary, sort_keys=True)}],
isError=False,
)
@staticmethod
def _progress(token: str | int, progress: int, total: int, message: str) -> dict[str, Any]:View on GitHub (pinned to 39ea8a1c6d)
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
Example fix
# before
workspace_scope = {}
review_sample = {"content": "draft text"}
# after
workspace_scope = {"roots": []}
review_sample = {"content": {"type": "text", "text": "draft text"}} Defensive patterns
Strategy: validation
Validate before calling
roots = responses["workspace_scope"].get("roots")
sample_content = responses["review_sample"].get("content", {})
if not isinstance(roots, list):
responses["workspace_scope"]["roots"] = []
if not isinstance(sample_content, dict):
raise ValueError("sampling content must be an object") Type guard
def valid_roots_and_sample(scope: object, sample: object) -> bool:
return (
isinstance(scope, dict) and isinstance(scope.get("roots"), list)
and isinstance(sample, dict) and isinstance(sample.get("content", {}), dict)
) Prevention
- Default missing roots to an empty list, not null
- Forward roots/list and createMessage results verbatim
- Write fixtures from captured real responses
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- review_sample must contain text
- -32600
- -32603
- _meta.{PROTOCOL_VERSION_KEY} is required
- _meta.{CLIENT_CAPABILITIES_KEY} is required
AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26).
Data as JSON: /api/errors/55b9b80a4f387963.
Report an issue: GitHub.