{"record":{"id":"45e51b950edd8001","repo":"PrefectHQ/fastmcp","slug":"server-discover-handler-returned-type-raw-name","errorCode":null,"errorMessage":"server/discover handler returned {type(raw).__name__}; expected DiscoverResult or mapping","messagePattern":"server/discover handler returned (.+?); expected DiscoverResult or mapping","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/low_level.py","lineNumber":362,"sourceCode":"            message = _mw_ctx.message\n            params = (\n                message.params.model_dump(by_alias=True, mode=\"json\", exclude_none=True)\n                if message.params is not None\n                else None\n            )\n            raw = await call_next(replace(ctx, params=params))\n            if isinstance(raw, mcp_types.DiscoverResult):\n                return raw\n            if isinstance(raw, Mapping):\n                result = dict(raw)\n                result_type = result.get(\"resultType\")\n                if (\n                    isinstance(result_type, str)\n                    and result_type not in mcp_types.CORE_RESULT_TYPES\n                ):\n                    return result\n                return mcp_types.DiscoverResult.model_validate(result)\n            raise TypeError(\n                \"server/discover handler returned \"\n                f\"{type(raw).__name__}; expected DiscoverResult or mapping\"\n            )\n\n        async with Context(fastmcp=fastmcp, session=ctx.session) as fastmcp_ctx:\n            mw_context = MiddlewareContext(\n                message=discover_message,\n                source=\"client\",\n                type=\"request\",\n                method=\"server/discover\",\n                fastmcp_context=fastmcp_ctx,\n            )\n            return await fastmcp._run_middleware(\n                mw_context,\n                cast(\"FastMCPCallNext[Any, Any]\", call_original_handler),\n            )\n\n    async def _run_initialize_mw(","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/low_level.py#L344-L380","documentation":"The low-level server/discover dispatcher expects the registered handler to return a DiscoverResult instance or a mapping that can be validated into one (unless the handler returned a raw string result outside CORE_RESULT_TYPES). Any other return type raises TypeError naming the actual type returned.","triggerScenarios":"Registering a custom server/discover handler that returns e.g. a list, a string that is a core result type name, a pydantic model of the wrong type, or None where a result is required.","commonSituations":"Implementing a custom discovery handler returning plain Python lists of servers; wrapping/middleware that accidentally transforms the result; migrating a handler after the DiscoverResult result-type contract was introduced.","solutions":["Return a DiscoverResult from the handler: return mcp_types.DiscoverResult(servers=[...]).","Return a dict matching the DiscoverResult schema so model_validate can coerce it.","If returning a string result intentionally, ensure it is not one of CORE_RESULT_TYPES or wrap it appropriately.","Inspect the handler for middleware wrappers that may be converting the result to an unsupported type."],"exampleFix":"// before\nasync def discover_handler(ctx, params):\n    return [\"server-a\", \"server-b\"]  # TypeError: list returned\n// after\nasync def discover_handler(ctx, params):\n    return mcp_types.DiscoverResult.model_validate({\"servers\": [\"server-a\", \"server-b\"]})","handlingStrategy":"type-guard","validationCode":"def valid_discover_result(raw) -> bool:\n    import mcp.types as mcp_types\n    return isinstance(raw, (mcp_types.DiscoverResult, dict))","typeGuard":"def is_discover_result(raw) -> bool:\n    import mcp.types as mcp_types\n    return isinstance(raw, mcp_types.DiscoverResult)","tryCatchPattern":"try:\n    result = await dispatch(\"server/discover\", ctx, params)\nexcept TypeError as e:\n    logger.error(\"Discover handler must return DiscoverResult/mapping: %s\", e)\n    raise","preventionTips":["Always build handler returns via mcp_types.DiscoverResult.model_validate(...)","Type-hint the handler's return as DiscoverResult and run a type checker","Check middleware wrappers preserve the DiscoverResult return type"],"tags":["discover","low-level","return-type"],"backgroundTag":"invalid-handler-return-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}