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

  1. Populate the list with at least one tool name, e.g. "allowedTools": ["read_file"].
  2. Delete the empty 'allowedTools'/'disabledTools' key from the server config to disable filtering.
  3. 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

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


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/03669eb8f3621408. Report an issue: GitHub.