{"record":{"id":"ca7e250349e3abfd","repo":"rohitg00/ai-engineering-from-scratch","slug":"name-must-be-a-non-empty-string","errorCode":null,"errorMessage":"name must be a non-empty string","messagePattern":"name must be a non-empty string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py","lineNumber":311,"sourceCode":"                raise ValueError(\"name must be a string\")\n            if name not in self.prompts:\n                raise ValueError(\"unknown prompt\")\n            return self._complete(\n                messages=[\n                    {\n                        \"role\": \"user\",\n                        \"content\": {\"type\": \"text\", \"text\": self.prompts[name]},\n                    }\n                ]\n            ), []\n        raise LookupError(f\"Method not found: {method}\")\n\n    def _call_tool(\n        self, params: dict[str, Any], metadata: dict[str, Any]\n    ) -> tuple[dict[str, Any], list[dict[str, Any]]]:\n        name = params[\"name\"]\n        if not isinstance(name, str) or not name:\n            raise ValueError(\"name must be a non-empty string\")\n        tool = self.tools.get(name)\n        if tool is None:\n            raise ValueError(\"unknown tool\")\n        arguments = tool.validate_arguments(params.get(\"arguments\", {}))\n        if name == \"prepare_review\":\n            return self._prepare_review(params, metadata, arguments), []\n\n        token = metadata.get(\"progressToken\")\n        notifications: list[dict[str, Any]] = []\n        if token is not None:\n            if not isinstance(token, (str, int)) or isinstance(token, bool):\n                raise ValueError(\"progressToken must be a string or integer\")\n            notifications = [\n                self._progress(token, 0, 1, \"starting\"),\n                self._progress(token, 1, 1, \"complete\"),\n            ]\n        value = tool.handler(arguments)\n        return self._complete(","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py#L293-L329","documentation":"_call_tool validates params['name'] before anything else: it must be a non-empty string. The guard rejects wrong-shape requests before registry lookup, mirroring JSON-RPC -32602 invalid params. It is purely a type/emptiness check, not a lookup failure.","triggerScenarios":"tools/call with params like {\"name\": 123}, {\"name\": \"\"}, {\"name\": [\"prepare_review\"]}, or a name key holding None.","commonSituations":"Client builds the tool name from unvalidated user input or config; an SDK serializes name as a non-string; test fixtures pass an empty string to probe validation.","solutions":["Pass the tool name as a non-empty string, e.g. {\"name\": \"prepare_review\", \"arguments\": {...}}","Validate the name type at the client boundary before sending the request","Fetch tools/list and copy an advertised name verbatim"],"exampleFix":"# before\nparams = {\"name\": \"\", \"arguments\": {}}\n\n# after\nparams = {\"name\": \"prepare_review\", \"arguments\": {\"topic\": \"api\"}}","handlingStrategy":"type-guard","validationCode":"name = payload.get(\"name\")\nif not isinstance(name, str) or not name:\n    raise ValueError(\"tools/call name must be a non-empty string\")\nserver.exchange(\"tools/call\", {\"name\": name, \"arguments\": payload.get(\"arguments\", {})})","typeGuard":"def is_nonempty_str(value: object) -> bool:\n    return isinstance(value, str) and len(value) > 0","tryCatchPattern":"try:\n    result = server.exchange(\"tools/call\", params)\nexcept ValueError as exc:\n    respond_error(request_id, -32602, str(exc))","preventionTips":["Validate tool name type and emptiness at the client boundary","Never build tool names from untyped user input","Keep a typed ToolCall dataclass so name is a string by construction"],"tags":["mcp","json-rpc","validation","tools"],"backgroundTag":"invalid-request-params","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}