pypa/pip · error · PEP723Exception
Multiple blocks found in
Error message
Multiple {name!r} blocks found in {scriptfile!r} What it means
PEP 723 inline script metadata uses exactly one '# /// script' fenced block in a Python script. pip's pep723_metadata() function found more than one matching block and raised PEP723Exception. A script must have at most one inline metadata block.
Solutions
- Search the script for all '# /// script' markers and keep only one
- Merge the dependencies from duplicate blocks into a single '# /// script' block
- Use a text editor or grep to locate the blocks: grep -n '# /// script' script.py
Example fix
# before — two blocks in script.py: # /// script # dependencies = ["requests"] # /// # ... later ... # /// script # dependencies = ["rich"] # /// # after — single merged block: # /// script # dependencies = ["requests", "rich"] # ///
Defensive patterns
Strategy: validation
Validate before calling
import re
REGEX = r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
def count_script_blocks(filepath: str) -> int:
with open(filepath) as f:
script = f.read()
return len([m for m in re.finditer(REGEX, script) if m.group("type") == "script"])
if count_script_blocks("script.py") > 1:
print("Duplicate PEP 723 blocks detected — merge them") Type guard
def has_single_pep723_block(filepath: str) -> bool:
"""Type guard: True if the file has exactly one '# /// script' block."""
import re
regex = r"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
with open(filepath) as f:
matches = [m for m in re.finditer(regex, f.read()) if m.group("type") == "script"]
return len(matches) == 1 Try / catch
from pip._internal.req.pep723 import pep723_metadata, PEP723Exception
try:
meta = pep723_metadata("script.py")
except PEP723Exception as e:
if "Multiple" in e.msg:
print("Fix: merge duplicate '# /// script' blocks into one")
else:
raise Prevention
- When merging scripts, search for '# /// script' and keep only one block
- Use a pre-commit hook that checks for duplicate PEP 723 blocks
- After editing inline metadata, grep for '# /// script' to confirm exactly one block
When it happens
Trigger: A Python script passed to pip's PEP 723 support (e.g. pip run script.py) contains two separate '# /// script' ... '# ///' sections. This can happen when merging scripts or when an editor/tool inserts a second metadata block.
Common situations: Concatenating two scripts that each had their own metadata block. An IDE plugin or tooling that auto-generates a metadata block without checking for an existing one. Copy-paste of a dependencies section.
Related errors
- Failed to parse TOML in
- File does not contain
- Invalid requirement
- Badly formatted data
- Configuration file could not be loaded.\n
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/5de8e2668b112dc7.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/req/pep723.py:26
class PEP723Exception(ValueError):
"""Raised to indicate a problem when parsing PEP 723 metadata from a script"""
def __init__(self, msg: str) -> None:
self.msg = msg
def pep723_metadata(scriptfile: str) -> dict[str, Any]:
with open(scriptfile, encoding="utf8") as f:
script = f.read()
name = "script"
matches = list(
filter(lambda m: m.group("type") == name, re.finditer(REGEX, script))
)
if len(matches) > 1:
raise PEP723Exception(f"Multiple {name!r} blocks found in {scriptfile!r}")
elif len(matches) == 1:
content = "".join(
line[2:] if line.startswith("# ") else line[1:]
for line in matches[0].group("content").splitlines(keepends=True)
)
try:
metadata = tomllib.loads(content)
except Exception as exc:
raise PEP723Exception(f"Failed to parse TOML in {scriptfile!r}") from exc
else:
raise PEP723Exception(
f"File does not contain {name!r} metadata: {scriptfile!r}"
)
return metadata
View on GitHub (pinned to f399c37189)