{"record":{"id":"0b478cd28b23b9f5","repo":"langchain-ai/deepagents","slug":"server-server-name-env-must-be-a-dictionary","errorCode":null,"errorMessage":"Server '{server_name}' 'env' must be a dictionary","messagePattern":"Server '(.+?)' 'env' must be a dictionary","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/mcp_tools.py","lineNumber":927,"sourceCode":"        if \"command\" not in server_config:\n            error_msg = f\"Server '{server_name}' missing required 'command' field\"\n            raise ValueError(error_msg)\n\n        if \"url\" in server_config:\n            error_msg = (\n                f\"Server '{server_name}' has type 'stdio' but also declares \"\n                \"a 'url' field. Remove 'url' or set \"\n                '`\"type\": \"http\"` (or `\"sse\"`) for a remote server.'\n            )\n            raise ValueError(error_msg)\n\n        if \"args\" in server_config and not isinstance(server_config[\"args\"], list):\n            error_msg = f\"Server '{server_name}' 'args' must be a list\"\n            raise TypeError(error_msg)\n\n        if \"env\" in server_config and not isinstance(server_config[\"env\"], dict):\n            error_msg = f\"Server '{server_name}' 'env' must be a dictionary\"\n            raise TypeError(error_msg)\n    else:\n        error_msg = (\n            f\"Server '{server_name}' has unsupported transport type '{server_type}'. \"\n            \"Supported types: stdio, sse, http\"\n        )\n        raise ValueError(error_msg)\n\n    auth = server_config.get(\"auth\")\n    if auth is not None:\n        if auth != \"oauth\":\n            msg = (\n                f\"Server '{server_name}' has unsupported auth value \"\n                f\"{auth!r}. Only 'oauth' is supported.\"\n            )\n            raise ValueError(msg)\n        if server_type == \"stdio\":\n            msg = (\n                f\"Server '{server_name}' uses stdio transport; \"","sourceCodeStart":909,"sourceCodeEnd":945,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/mcp_tools.py#L909-L945","documentation":"For stdio servers, `env` supplies environment variables to the child process and must be a dictionary of string names to string values. `_validate_server_config` raises this TypeError when `env` is present but is not a dict (e.g. a list or string), because the subprocess environment can only be built from a mapping.","triggerScenarios":"A stdio server entry has `env` as a non-dict — e.g. `\"env\": \"API_KEY=abc\"` or `\"env\": [\"A=1\", \"B=2\"]` — validated via `select_server`, `resolve_and_load_mcp_tools`, or the batch config validators.","commonSituations":"Authoring env as a shell-style 'KEY=value' string or list from a Docker/CLI habit; YAML producing a list from sequence syntax; copying `headers`-style list config into `env`; programmatically joining env entries with newlines.","solutions":["Convert `env` to a dictionary: {\"KEY\": \"value\", ...}.","Parse a 'KEY=value' string/list into a dict by splitting on the first '=' before assigning.","Omit `env` if no custom environment variables are needed (it is optional; parent env is inherited).","Validate env values are strings where required by the child process."],"exampleFix":"// before\n\"env\": \"API_KEY=abc DEBUG=1\"\n// after\n\"env\": {\"API_KEY\": \"abc\", \"DEBUG\": \"1\"}","handlingStrategy":"type-guard","validationCode":"def validate_env(name: str, cfg: dict) -> None:\n    env = cfg.get(\"env\")\n    if env is not None and not (isinstance(env, dict) and all(isinstance(v, str) for v in env.values())):\n        raise TypeError(f\"Server '{name}' 'env' must be a dictionary of string values\")","typeGuard":"def has_valid_env(cfg: dict) -> bool:\n    env = cfg.get(\"env\")\n    return env is None or (isinstance(env, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in env.items()))","tryCatchPattern":"try:\n    tools = resolve_and_load_mcp_tools(config)\nexcept TypeError as e:\n    if \"'env' must be a dictionary\" in str(e):\n        name = extract_server_name(str(e))\n        raw = config[\"servers\"][name].get(\"env\")\n        pairs = raw.split() if isinstance(raw, str) else raw\n        config[\"servers\"][name][\"env\"] = dict(p.split(\"=\", 1) for p in pairs)\n        tools = resolve_and_load_mcp_tools(config)\n    else:\n        raise","preventionTips":["Author env as a mapping {\"KEY\": \"value\"}, not a 'KEY=value' string or list.","Quote values in YAML to avoid type coercion of numbers and booleans.","Remember env is optional — the child process inherits the parent environment by default.","Validate env types in a config pre-check script."],"tags":["mcp","config-validation","typeerror","stdio","environment"],"backgroundTag":"mcp-server-config-invalid","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}