podman-container-tools/podman · error · ValueError

multiple `else` in the same `if`

Error message

multiple `else` in the same `if`

What it means

Raised when render() sees a second '<< else >>' for the same '<< if >>' frame (frame['seen_else'] is already True). Each if-frame supports exactly one else branch; there is no elseif/elif construct in this mini-language. Usually a copy-paste of a two-branch block that already contained an else.

Source

Thrown at hack/markdown-preprocess:87

            # write literal up to token
            literal = text[pos:m.start()]
            if is_active():
                out.append(literal)
            pos = m.end()

            inner = m.group(1).strip()

            # control blocks
            if inner.startswith("if ") and len(inner[3:].strip().split(" ")) in [1, 2]:
                cond = inner[3:].strip()
                stack.append({"active": is_active() and truthy(cond), "seen_else": False})
                continue
            if inner == "else":
                if not stack:
                    raise ValueError("`else` without `if`")
                frame = stack[-1]
                if frame["seen_else"]:
                    raise ValueError("multiple `else` in the same `if`")
                frame["seen_else"] = True
                parent_active = all(f["active"] for f in stack[:-1])
                frame["active"] = parent_active and not frame["active"]
                continue
            if inner == "endif":
                if not stack:
                    raise ValueError("`end` without `if`")
                stack.pop()
                continue

            # inline "X if cond else Y" ---
            if " if " in inner and " else " in inner:
                try:
                    # split by " if " then " else "
                    then_part, rest = inner.split(" if ", 1)
                    cond, else_part = rest.split(" else ", 1)
                    cond = cond.strip()
                    chosen = then_part if truthy(cond) else else_part

View on GitHub (pinned to a2409076ef)

Solutions

  1. Rewrite as two blocks: '<< if VAR >>A<< endif >>' plus '<< if not VAR >>B or C<< endif >>'
  2. Or move the third case into an inline token: '<< "B" if not VAR else "A" >>'
  3. Delete whichever else branch is obsolete

Example fix

# before
<< if is_quadlet >>A<< else >>B<< else >>C<< endif >>

# after
<< if is_quadlet >>A<< else >>B<< endif >>
<< if not is_quadlet >>C<< endif >>
Defensive patterns

Strategy: validation

Validate before calling

import re, pathlib
def lint(text, name):
    stack = []
    for m in re.finditer(r'<<(.*?)>>', text, re.DOTALL):
        inner = m.group(1).strip()
        if inner.startswith('if ') and len(inner[3:].split()) in (1, 2):
            stack.append(False)
        elif inner == 'else':
            assert stack, f'{name}: `else` without `if`'
            assert not stack[-1], f'{name}: multiple `else` near offset {m.start()}'
            stack[-1] = True
        elif inner == 'endif':
            assert stack, f'{name}: `end` without `if`'
            stack.pop()
    assert not stack, f'{name}: unclosed `if` block(s)'
for p in pathlib.Path('docs/source/markdown/options').glob('*.md'):
    lint(p.read_text(), str(p))

Prevention

When it happens

Trigger: An options/*.md file contains '<< if VAR >>A<< else >>B<< else >>C<< endif >>', or text like 'if X ... else ... else if Y' translated literally into tokens (the second else belongs to the same frame).

Common situations: Translating shell/Python if/elif/else prose into man-page conditionals; duplicating a branch block and forgetting to remove the embedded else; attempting three-way branching in a template that only supports two.

Related errors


AI-assisted analysis of podman-container-tools/podman@a2409076ef (2026-08-15). Data as JSON: /api/errors/96bfa350afc41924. Report an issue: GitHub.