bmad-code-org/BMAD-METHOD · critical · SystemExit
error: Python 3.11+ is required (stdlib `tomllib` not found)
Error message
error: Python 3.11+ is required (stdlib `tomllib` not found).
What it means
This is a runtime interpreter-version guard, not a logic error. The script imports `load_central_config` from the local `config_utils` module, which itself does `import tomllib` (config_utils.py:5). `tomllib` is a standard-library module that ships only with Python 3.11 and newer. When run on Python < 3.11, that import raises `ModuleNotFoundError(name='tomllib')`; the wrapper narrows on `error.name == 'tomllib'`, prints a one-line actionable message, and terminates the process via `SystemExit(3)`. It exists because the repository declares no `pyproject.toml` / `requires-python` / `.python-version`, so this import-time check is the only thing keeping the tool from failing later with a confusing traceback.
Source
Thrown at src/scripts/resolve_config.py:21
# requires-python = ">=3.11"
# ///
"""Resolve BMad's four central TOML layers to JSON."""
import argparse
import json
import sys
from pathlib import Path
# Installed scripts are consumer files, not a location for interpreter caches.
sys.dont_write_bytecode = True
try:
from config_utils import ConfigError, load_central_config
except ModuleNotFoundError as error:
if error.name != "tomllib":
raise
sys.stderr.write("error: Python 3.11+ is required (stdlib `tomllib` not found).\n")
raise SystemExit(3) from None
_MISSING = object()
def extract_key(data, dotted_key: str):
current = data
for part in dotted_key.split("."):
if isinstance(current, dict) and part in current:
current = current[part]
else:
return _MISSING
return current
def main() -> int:
parser = argparse.ArgumentParser(
description="Resolve BMad central config using four-layer TOML merge."View on GitHub (pinned to b70486b9bd)
Solutions
- Run the script with Python 3.11+: `python3.11 src/scripts/resolve_config.py` (or `python3.12`). Verify with `python3 --version` first.
- Recreate the virtualenv on a 3.11+ base: `python3.12 -m venv .venv && source .venv/bin/activate`, then re-run.
- Pin the project to a 3.11+ interpreter in your version manager: `pyenv local 3.12` / `mise use python@3.12` / `asdf local python 3.12.x`.
- If the interpreter is fixed at < 3.11 and cannot be upgraded, install the `tomli` backport and add a shim: `pip install tomli` plus `if sys.version_info < (3,11): import tomli as tomllib` in config_utils.py (only if the project owner accepts backport support — this is a code change, not a config fix).
- On CI, bump the Python setup step: `actions/setup-python@v5` with `python-version: '3.11'` or newer, or update the Docker base image to `python:3.11-slim`+.
Example fix
# before — shebang floats to whatever 'python3' resolves to
#!/usr/bin/env python3
# after — pin to a 3.11+ interpreter explicitly
#!/usr/bin/env python3.12
# or, in CI (.github/workflows/*.yml)
# before
- uses: actions/setup-python@v5
with:
python-version: '3.10'
# after
- uses: actions/setup-python@v5
with:
python-version: '3.12' Defensive patterns
Strategy: validation
Validate before calling
import sys
MIN_PY = (3, 11)
if sys.version_info < MIN_PY:
sys.exit(
f"error: Python {MIN_PY[0]}.{MIN_PY[1]}+ is required "
f"(running {sys.version_info.major}.{sys.version_info.minor})."
)
# Safe to invoke resolve_config / config_utils here — tomllib is guaranteed present.
import subprocess, sys
subprocess.run([sys.executable, "src/scripts/resolve_config.py"], check=True) Try / catch
# The guard raises SystemExit(3) at import time, so catch it only at a
# process/subprocess boundary — never around the import itself, which would
# mask a genuinely broken environment.
import subprocess, sys
proc = subprocess.run(
[sys.executable, "src/scripts/resolve_config.py"],
capture_output=True, text=True,
)
if proc.returncode == 3 and "tomllib" in proc.stderr:
raise RuntimeError(
"resolve_config needs Python 3.11+; current interpreter is "
f"{sys.version.split()[0]}."
)
raise SystemExit(proc.returncode) Prevention
- Pin the project interpreter explicitly: add a `.python-version` (pyenv/asdf/mise) or `requires-python = '>=3.11'` in a `pyproject.toml` so the failure surfaces at install time, not at first run.
- In wrappers and CI, call the script via the venv's absolute interpreter (`$VIRTUAL_ENV/bin/python` or `python3.12`) rather than a bare `python3` that PATH can resolve differently across machines.
- Add a one-line preflight check at the top of any orchestrator: `assert sys.version_info >= (3, 11), 'Python 3.11+ required (tomllib).'`.
- Lock CI to a 3.11+ matrix and fail fast on older versions; do not let a 3.10 cell pass and accumulate broken artifacts.
- Document the minimum interpreter in the README next to the install command so users create the venv with the right base.
When it happens
Trigger: Invoking `resolve_config.py` (directly or through a wrapper) with an interpreter whose `sys.version_info < (3, 11)`. Concretely: `python3.10 src/scripts/resolve_config.py`, or any `#!/usr/bin/env python3` shebang that resolves to a 3.10-or-older `python3` on PATH; running the project's tests with the wrong interpreter; a venv created from a pre-3.11 base interpreter; or a CI image pinned to an older Python. The error fires before any config file is read, so missing or malformed `*.toml` is NOT a cause.
Common situations: 1) System `python3` on older LTS distros (e.g. Ubuntu 20.04 ships 3.8, Debian 11 ships 3.9) resolving the shebang. 2) A virtualenv built from a pre-3.11 base interpreter while the developer assumes `python3` means 'latest'. 3) pyenv / asdf / mise shims pointing at an older Python. 4) CI matrix accidentally including 3.9/3.10, or a Docker base image like `python:3.10-slim`. 5) A toolchain manager (conda, uv, poetry) that created the env with an older default. 6) An alias `alias python=python3.10` lingering in the shell.
Related errors
- error: Python 3.11+ is required (stdlib `tomllib` not found)
- {label} must be a list of tables
- {item_label} must be a table
- duplicate review layer id `{identifier}`
- render source escapes skill directory: {name}
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/d8a08e443a8816d8.
Report an issue: GitHub.