langchain-ai/deepagents · error · ValueError
Invalid {SERVER_ENV_PREFIX}{suffix}: expected a JSON string
Error message
Invalid {SERVER_ENV_PREFIX}{suffix}: expected a JSON string list What it means
`_read_env_str_list` raises this `ValueError` when a `DEEPAGENTS_CODE_SERVER_*` variable parses as valid JSON (so error 38 did not fire) but the parsed value is not a list of strings — it may be a JSON string, number, object, a list of non-strings, or an empty/mixed list depending on the caller. The server expects a JSON array of string values for list-shaped configuration, and it deliberately fails closed rather than coercing.
Source
Thrown at libs/code/deepagents_code/_server_config.py:80
return None
try:
return json.loads(raw)
except json.JSONDecodeError as exc:
msg = (
f"Failed to parse {SERVER_ENV_PREFIX}{suffix} as JSON: {exc}. "
f"Value was: {raw[:200]!r}"
)
raise ValueError(msg) from exc
def _read_env_str_list(suffix: str) -> tuple[str, ...]:
raw = _read_env_json(suffix)
if raw is None:
return ()
if isinstance(raw, list) and all(isinstance(item, str) for item in raw):
return tuple(raw)
msg = f"Invalid {SERVER_ENV_PREFIX}{suffix}: expected a JSON string list"
raise ValueError(msg)
def _read_env_allow_fs_tools() -> list[FsToolName] | None:
"""Read and shape-validate the `ALLOW_FS_TOOLS` filesystem allowlist.
The parent writes only an absent variable (unrestricted — `None`, which is
also what `--allow-fs-tools all` collapses to) or a non-empty JSON list of
tool names (`main._parse_allow_fs_tools_flag`). This runs in the server
subprocess, where the variable could be tampered with, so — because the
value is a security control — any unrecognized shape must fail closed
(raise) rather than fall through to an unrestricted filesystem.
(`_read_env_json` already fails closed on malformed JSON.)
`[]` and unknown tool names are rejected here, not deferred downstream, so
the returned list genuinely satisfies `list[FsToolName]` and the `cast`
asserts membership that was actually checked. Importing `deepagents` here is
fine: the subprocess already imports the SDK to build the agent (this is not
the arg-parsing hot path guarded in `main`). The `"read_file"` requirementView on GitHub (pinned to a1af029e6e)
Solutions
- Set the variable to a JSON array of strings: `export DEEPAGENTS_CODE_SERVER_<SUFFIX>='["item1","item2"]'`.
- Verify the shape: run `python -c "import json,os;v=json.loads(os.environ['DEEPAGENTS_CODE_SERVER_<SUFFIX>']);assert isinstance(v,list) and all(isinstance(i,str) for i in v)"`.
- If the variable should not be set at all, unset it rather than exporting an empty string or non-list JSON value.
- Fix the writer side to use `json.dumps(["item1", "item2"])` before placing the value in the environment.
Example fix
// before (shell) export DEEPAGENTS_CODE_SERVER_EXTRA_TOOLS="grep,glob" // after (shell) export DEEPAGENTS_CODE_SERVER_EXTRA_TOOLS='["grep","glob"]'
Defensive patterns
Strategy: type-guard
Validate before calling
import json, os
def env_str_list_valid(suffix: str) -> bool:
raw = os.environ.get(f"DEEPAGENTS_CODE_SERVER_{suffix}")
if raw is None:
return True
try:
value = json.loads(raw)
except json.JSONDecodeError:
return False
return isinstance(value, list) and all(isinstance(i, str) for i in value) Type guard
import json
from typing import TypeGuard
def is_str_list(value: object) -> TypeGuard[list[str]]:
return isinstance(value, list) and all(isinstance(i, str) for i in value) Try / catch
try:
config = ServerConfig.from_env()
except ValueError as exc:
if "expected a JSON string list" in str(exc):
raise ConfigError(f"re-export variable as a JSON string array: {exc}") from exc
raise Prevention
- Export list config as '["a","b"]' — an array of quoted strings, not a CSV string.
- Remember a bare JSON string or object fails this check even though it is valid JSON.
- Generate values with json.dumps(list_of_strings) on the writer side.
- Prefer unsetting the variable over setting an empty or wrong-shaped placeholder.
When it happens
Trigger: Setting a list-shaped `DEEPAGENTS_CODE_SERVER_*` variable (consumed via `_read_env_str_list` from `from_env`) to `'"grep,glob"'` (a JSON string, not array), `'[1,2]'`, `'{"a":1}'`, `'true'`, or `[]` where a non-empty list of tool names is required downstream.
Common situations: Users exporting a comma-separated string thinking it will be split; quoting mistakes turning the intended array into a single JSON string; a parent process writing a JSON object instead of an array; CI templating that renders `["a","b"]` with escaped quotes stripped, yielding a string value.
Related errors
- Failed to parse {SERVER_ENV_PREFIX}{suffix} as JSON: {exc}.
- Could not determine the home directory: set $HOME, or set DE
- Home directory is not absolute: {launch_home}. Set $HOME to
- Invalid DEEPAGENTS_HOME {configured!r}: use an absolute path
- Invalid {SERVER_ENV_PREFIX}ALLOW_FS_TOOLS value: {raw!r}; ex
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/dfce5d124540a1c4.
Report an issue: GitHub.