podman-container-tools/podman · error · ValueError

undefined variable: {name}

Error message

undefined variable: {name}

What it means

Raised by Preprocessor.render() when a conditional token references a name that is not a key of the context dict. The context is built in insert_file (hack/markdown-preprocess:206) and currently contains exactly one variable: {"is_quadlet": bool}. So inside docs/source/markdown/options/*.md the only valid conditions are 'is_quadlet' and 'not is_quadlet'; any other name in << if VAR >>, << if not VAR >>, or an inline '<<X if VAR else Y>>' raises this ValueError. Note the whole render runs inside process()'s per-line try, so it usually surfaces wrapped as "Error while processing ... line '@@option foo'" with this message as __cause__.

Source

Thrown at hack/markdown-preprocess:58

        << "foo" if variable else "bar" >>
        ```

        Returns the rendered text.
        """
        # Match << ... >>
        TOK = re.compile(r"<<(.*?)>>", re.DOTALL)
        out = []
        pos = 0
        stack = []  # each frame: {"active": bool, "seen_else": bool}

        def is_active():
            return all(f["active"] for f in stack)

        def get_variable(name: str):
            v = context.get(name, None)
            if v is None:
                raise ValueError(f"undefined variable: {name}")
            return v

        def truthy(name: str) -> bool:
            name = name.strip()
            if name.startswith("not "):
                v = get_variable(name[4:].strip())
                return not bool(v)
            return bool(get_variable(name))

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

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

View on GitHub (pinned to a2409076ef)

Solutions

  1. Rename the variable in the .md option file to 'is_quadlet' (or 'not is_quadlet')
  2. If a genuinely new variable is needed, add it to the context dict in insert_file(): self.render(fh_included.read(), {"is_quadlet": is_quadlet, "myvar": value})
  3. Read the __cause__ of the wrapping 'Error while processing {infile} line' exception to find which option file and line contain the bad token
  4. grep the options dir for the bad name: grep -rn '<< if ' docs/source/markdown/options/

Example fix

# docs/source/markdown/options/pod-create.md (before)
<< if quadlet >>**--pod**=...<< endif >>

# after
<< if is_quadlet >>**--pod**=...<< endif >>
Defensive patterns

Strategy: validation

Validate before calling

# Lint option files before running the preprocessor
import re, pathlib, sys
ALLOWED = {'is_quadlet'}
TOK = re.compile(r'<<(.*?)>>', re.DOTALL)
bad = []
for p in pathlib.Path('docs/source/markdown/options').glob('*.md'):
    for m in TOK.finditer(p.read_text()):
        inner = m.group(1).strip()
        cond = None
        if inner.startswith('if ') and len(inner[3:].split()) in (1, 2):
            cond = inner[3:].strip()
        elif ' if ' in inner and ' else ' in inner:
            _, rest = inner.split(' if ', 1)
            cond = rest.split(' else ', 1)[0].strip()
        if cond is not None:
            var = cond[4:].strip() if cond.startswith('not ') else cond
            if var not in ALLOWED:
                bad.append(f'{p}: undefined variable {var!r}')
if bad:
    sys.exit('\n'.join(bad))

Prevention

When it happens

Trigger: An options/*.md file (included via @@option from a *.md.in man page) contains e.g. '<< if quadlet >>' instead of '<< if is_quadlet >>', or an inline token like '<< "yes" if enabled else "no" >>' where 'enabled' is not a context key. get_variable() finds context.get(name, None) is None and raises.

Common situations: Doc authors inventing a new variable name (quadlet, pod, remote) without extending the context dict in insert_file; copy-pasting Jinja-style conditionals from other docs; renaming is_quadlet and missing occurrences in shared option files (which are reused across many man pages).

Related errors


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