langchain-ai/deepagents · error · ValueError
Server '{server_name}' '{field_name}' must be non-empty; omi
Error message
Server '{server_name}' '{field_name}' must be non-empty; omit the field to disable filtering. What it means
An `allowedTools` or `disabledTools` field present in a server config must contain at least one tool name. An empty list is treated as a config mistake rather than 'filter nothing', so `_validate_tool_filter_fields` raises this ValueError with a hint: omit the field entirely if you don't want filtering.
Source
Thrown at libs/code/deepagents_code/mcp_tools.py:1006
raise ValueError(error_msg)
for field_name in ("allowedTools", "disabledTools"):
if field_name not in server_config:
continue
value = server_config[field_name]
if not isinstance(value, list) or not all(
isinstance(item, str) for item in value
):
error_msg = (
f"Server '{server_name}' '{field_name}' must be a list of strings"
)
raise TypeError(error_msg)
if not value:
error_msg = (
f"Server '{server_name}' '{field_name}' must be non-empty;"
" omit the field to disable filtering."
)
raise ValueError(error_msg)
def _looks_like_comment(doc: str, lineno: int) -> bool:
"""Return `True` if the offending line *begins* with `//` or `/*`.
Only the failing line is checked, and only its leading characters (after
stripping indentation). A `url` value such as `"url": "https://..."`
begins with a quote, not `//`, so a URL scheme inside a quoted string
never triggers a false comment hint.
Args:
doc: Full source text that failed to parse.
lineno: 1-based line number of the error; out-of-range values
return `False`.
Returns:
`True` when the stripped failing line starts with `//` or `/*`.
"""View on GitHub (pinned to a1af029e6e)
Solutions
- Populate the list with at least one tool name, e.g. "allowedTools": ["read_file"].
- Delete the empty 'allowedTools'/'disabledTools' key from the server config to disable filtering.
- In programmatic builders, only emit the key when the list is non-empty.
Example fix
// before
{"mcpServers": {"fs": {"command": "mcp-server-fs", "disabledTools": []}}}
// after (filtering disabled entirely)
{"mcpServers": {"fs": {"command": "mcp-server-fs"}}} Defensive patterns
Strategy: validation
Validate before calling
def check_filter_nonempty(server, field):
if field in server and not server[field]:
del server[field] # or raise: empty list means 'omit the field' Type guard
def is_empty_filter(server: dict, field: str) -> bool:
return server.get(field) == [] Try / catch
try:
load_mcp_config(path)
except ValueError as e:
if "must be non-empty" in str(e):
strip_empty_filter_keys(path)
else:
raise Prevention
- Omit the key entirely when you don't want filtering; never serialize empty lists.
- In UIs/builders, drop the field when the user selects zero tools.
- Lint the config: flag any empty-array value.
When it happens
Trigger: Server config like {"mcpServers": {"fs": {"command": "mcp-server-fs", "allowedTools": []}}} — the key exists but the list is empty, raised during _validate_server_config.
Common situations: Programmatic config builders that initialize the key to [] and never populate it; UIs that let users deselect all tools and serialize the empty selection; cleaning up a config by deleting the tool names but leaving the key.
Related errors
- Server '{server_name}' cannot set both 'allowedTools' and 'd
- Invalid MCP config at {mcp_config_path}: {exc}
- Server '{server_name}' '{field_name}' must be a list of stri
- MCP config must contain 'mcpServers' field. Expected format:
- 'mcpServers' field must be a dictionary
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/03669eb8f3621408.
Report an issue: GitHub.