{"record":{"id":"d8ab8ad6f616eca0","repo":"podman-container-tools/podman","slug":"unclosed-if-block-s","errorCode":null,"errorMessage":"unclosed `if` block(s)","messagePattern":"unclosed `if` block\\(s\\)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"hack/markdown-preprocess","lineNumber":122,"sourceCode":"                    cond = cond.strip()\n                    chosen = then_part if truthy(cond) else else_part\n                    if is_active():\n                        out.append(chosen.strip().strip(\"'\\\"\"))\n                except Exception as e:\n                    raise ValueError(f\"Invalid inline if/else syntax: {inner}\") from e\n                continue\n\n            # Unrecognized token (e.g. `<<a|b>>` for replace_type, or `<<subcommand>>`):\n            # preserve verbatim so downstream processing can handle it.\n            if is_active():\n                out.append(m.group(0))\n\n        # trailing literal\n        if is_active():\n            out.append(text[pos:])\n\n        if stack:\n            raise ValueError(\"unclosed `if` block(s)\")\n        return \"\".join(out)\n\n    def process(self, infile:str):\n        \"\"\"\n        Main calling point: preprocesses one file\n        \"\"\"\n        self.infile = infile\n        # Some options are the same between containers and pods; determine\n        # which description to use from the name of the source man page.\n        self.pod_or_container = 'container'\n        if '-pod-' in infile or '-kube-' in infile:\n            self.pod_or_container = 'pod'\n\n        # foo.md.in -> foo.md -- but always write to a tmpfile\n        outfile = os.path.splitext(infile)[0]\n        outfile_tmp = outfile + '.tmp.' + str(os.getpid())\n\n        with open(infile, 'r', encoding='utf-8') as fh_in, open(outfile_tmp, 'w', encoding='utf-8', newline='\\n') as fh_out:","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/podman-container-tools/podman/blob/a2409076ef2fef60ad9ac046375dedc7d9410ef4/hack/markdown-preprocess#L104-L140","documentation":"Raised at the end of render() when the control-block stack is still non-empty: at least one '<< if ... >>' was never closed with '<< endif >>'. Unclosed blocks also silently swallow the file's trailing literal (it is only appended when is_active()). A typo'd closer such as '<< end >>' or '<< ENDIF >>' is not recognized (it is preserved verbatim as an unrecognized token) and leaves the frame open, producing this error at EOF.","triggerScenarios":"An options/*.md file ends with '<< if is_quadlet >>' ... and no '<< endif >>'; or the closer is misspelled ('<< end >>', '<< fi >>', '<<Endif>>'), so the stack never empties.","commonSituations":"Appending new conditional text at the bottom of a shared option file and forgetting the closer; renaming/reformatting tokens with an editor that changed case; block accidentally spanning past end of file during a merge conflict resolution.","solutions":["Add one '<< endif >>' per open '<< if >>' at the end of the block","Check the closer's exact spelling: lowercase 'endif' with single spaces inside << >>","grep -c '<< if ' and '<< endif >>' in the file and make the counts match"],"exampleFix":"# before\n<< if is_quadlet >>\n**--pod**=...\n\n# after\n<< if is_quadlet >>\n**--pod**=...\n<< endif >>","handlingStrategy":"validation","validationCode":"import re, pathlib\ndef lint(text, name):\n    stack = 0\n    for m in re.finditer(r'<<(.*?)>>', text, re.DOTALL):\n        inner = m.group(1).strip()\n        if inner.startswith('if ') and len(inner[3:].split()) in (1, 2):\n            stack += 1\n        elif inner == 'else':\n            assert stack > 0, f'{name}: `else` without `if`'\n        elif inner == 'endif':\n            assert stack > 0, f'{name}: `end` without `if`'\n            stack -= 1\n    assert stack == 0, f'{name}: {stack} unclosed `if` block(s)'\nfor p in pathlib.Path('docs/source/markdown/options').glob('*.md'):\n    lint(p.read_text(), str(p))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["The closer token is exactly '<< endif >>' — '<< end >>' and '<< ENDIF >>' are preserved verbatim and leave the block open","grep-check balance before committing: counts of '<< if ' and '<< endif >>' must match per file","Run the preprocessor locally (./hack/markdown-preprocess) before opening docs PRs; it is fast and catches this immediately"],"tags":["markdown","docs","preprocessor","conditionals"],"backgroundTag":null,"analyzedSha":"a2409076ef2fef60ad9ac046375dedc7d9410ef4","analyzedAt":"2026-08-15T15:57:05.625Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}