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_partView on GitHub (pinned to a2409076ef)
Solutions
- Rewrite as two blocks: '<< if VAR >>A<< endif >>' plus '<< if not VAR >>B or C<< endif >>'
- Or move the third case into an inline token: '<< "B" if not VAR else "A" >>'
- 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
- Remember the template has exactly two branches per if — plan A/B wording before writing
- For three-way content use two ifs ('if' and 'if not') instead of a second else
- Run the stack lint in CI; it detects else-without-if, duplicate else, stray endif, and unclosed if in one pass
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
- `else` without `if`
- `end` without `if`
- unclosed `if` block(s)
- undefined variable: {name}
- Invalid inline if/else syntax: {inner}
AI-assisted analysis of podman-container-tools/podman@a2409076ef (2026-08-15).
Data as JSON: /api/errors/96bfa350afc41924.
Report an issue: GitHub.