pypa/pip · error · ValueError

Invalid section heading

Error message

Invalid section heading

What it means

Raised as ValueError from split_sections when a line begins with '[' but does not end with ']'. split_sections parses INI-like section headers ('[name]'); a line that opens a bracket without closing it is treated as a malformed section heading.

Source

Thrown at src/pip/_vendor/pkg_resources/__init__.py:3538

def split_sections(s: _NestedStr) -> Iterator[tuple[str | None, list[str]]]:
    """Split a string or iterable thereof into (section, content) pairs

    Each ``section`` is a stripped version of the section header ("[section]")
    and each ``content`` is a list of stripped lines excluding blank lines and
    comment-only lines.  If there are any such lines before the first section
    header, they're returned in a first ``section`` of ``None``.
    """
    section = None
    content = []
    for line in yield_lines(s):
        if line.startswith("["):
            if line.endswith("]"):
                if section or content:
                    yield section, content
                section = line[1:-1].strip()
                content = []
            else:
                raise ValueError("Invalid section heading", line)
        else:
            content.append(line)

    # wrap up last segment
    yield section, content


def _mkstemp(*args, **kw):
    old_open = os.open
    try:
        # temporarily bypass sandboxing
        os.open = os_open
        return tempfile.mkstemp(*args, **kw)
    finally:
        # and then put it back
        os.open = old_open

View on GitHub (pinned to d7d0d0a394)

Solutions

  1. Fix the malformed header so it is '[group]' with matching brackets.
  2. If the line is genuine content starting with '[', escape or restructure it so it does not look like a section.
  3. Validate the file as valid INI (configparser) before feeding it to split_sections.

Example fix

# before (entry_points.txt)
[console_scripts
foo = mod:fn

# after
[console_scripts]
foo = mod:fn
Defensive patterns

Strategy: validation

Validate before calling

def balanced_section(line: str) -> bool:
    s = line.strip()
    return not s.startswith('[') or s.endswith(']')
if all(balanced_section(l) for l in text.splitlines()):
    list(split_sections(text))

Type guard

def is_valid_section_line(line: str) -> bool:
    s = line.strip()
    return not s.startswith('[') or (s.startswith('[') and s.endswith(']'))

Try / catch

try:
    sections = list(split_sections(text))
except ValueError as e:
    if 'Invalid section heading' in str(e):
        # fix the unmatched bracket, then retry
        ...
    raise

Prevention

When it happens

Trigger: Calling split_sections (directly or via parse_map) on text containing a line like '[console_scripts' (missing closing bracket), or a line beginning with '[' that is actually data with an embedded bracket.

Common situations: Hand-edited entry_points.txt or requires.txt with a typo in a section header, or data that legitimately starts with '[' but was not meant as a section (and is not bracket-balanced).

Related errors


AI-assisted analysis of pypa/pip@d7d0d0a394 (2026-08-04). Data as JSON: /data/errors/81ef9d79f6b8b66a.json. Report an issue: GitHub.