{"record":{"id":"c35ee55e5a593ff4","repo":"CoplayDev/unity-mcp","slug":"command-parameters-must-be-a-dict-for-http-transpo","errorCode":null,"errorMessage":"Command parameters must be a dict for HTTP transport","messagePattern":"Command parameters must be a dict for HTTP transport","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Server/src/transport/unity_transport.py","lineNumber":57,"sourceCode":"        return None\n\n\nasync def send_with_unity_instance(\n    send_fn: Callable[..., Awaitable[T]],\n    unity_instance: str | None,\n    *args,\n    user_id: str | None = None,\n    **kwargs,\n) -> T:\n    if _is_http_transport():\n        if not args:\n            raise ValueError(\"HTTP transport requires command arguments\")\n        command_type = args[0]\n        params = args[1] if len(args) > 1 else kwargs.get(\"params\")\n        if params is None:\n            params = {}\n        if not isinstance(params, dict):\n            raise TypeError(\n                \"Command parameters must be a dict for HTTP transport\")\n\n        # Auto-resolve user_id from HTTP request API key (remote-hosted mode)\n        if user_id is None:\n            user_id = await _resolve_user_id_from_request()\n\n        # Auth check\n        if config.http_remote_hosted and not user_id:\n            return normalize_unity_response(\n                MCPResponse(\n                    success=False,\n                    error=\"auth_required\",\n                    message=\"API key required\",\n                ).model_dump()\n            )\n\n        retry_on_reload = kwargs.pop(\"retry_on_reload\", True)\n        if not isinstance(retry_on_reload, bool):","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/CoplayDev/unity-mcp/blob/c21bf496bca87d54e75bad048563c3adb1782081/Server/src/transport/unity_transport.py#L39-L75","documentation":"Raised by send_with_unity_instance in HTTP mode when the resolved params value is not a dict. The HTTP request body is built from a JSON object, so a non-dict (list, str, None after coercion, custom object) cannot be serialized into the expected command payload shape.","triggerScenarios":"args[1] (or kwargs['params']) is present but isinstance(params, dict) is false. The guard at unity_transport.py:55-57 fires.","commonSituations":"A tool wrapper passed a Pydantic model or a JSON string instead of a plain dict; params came from json.loads of an array; a refactor changed the params type without adapting the call site.","solutions":["Pass params as a plain dict (use model_dump() for Pydantic models, or json.loads then re-wrap).","Validate isinstance(params, dict) at the wrapper boundary before calling send_with_unity_instance.","Normalize at the call site: params = dict(params) when params is a mapping-like object."],"exampleFix":"// before\nawait send_with_unity_instance(send_fn, instance, 'manage_gameobject', some_model)\n// after\nawait send_with_unity_instance(send_fn, instance, 'manage_gameobject', some_model.model_dump())","handlingStrategy":"type-guard","validationCode":"if not isinstance(params, dict):\n    params = params.model_dump() if hasattr(params, 'model_dump') else dict(params)\nif not isinstance(params, dict):\n    raise TypeError('params must be a dict')","typeGuard":"def is_command_params(v) -> bool:\n    return isinstance(v, dict)","tryCatchPattern":"try:\n    await send_with_unity_instance(send_fn, instance, cmd, params)\nexcept TypeError as e:\n    if 'must be a dict' in str(e):\n        await send_with_unity_instance(send_fn, instance, cmd, dict(params))","preventionTips":["Coerce Pydantic models with model_dump() before sending","Never pass raw JSON strings or lists as params","Assert isinstance(params, dict) at the wrapper boundary"],"tags":["transport","http","type-guard","api-misuse"],"backgroundTag":null,"analyzedSha":"c21bf496bca87d54e75bad048563c3adb1782081","analyzedAt":"2026-08-13T17:36:56.095Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}