podman-container-tools/podman · error · Exception

'{matchobj[0]}' matches 'pod' in both left and right sides

Error message

'{matchobj[0]}' matches 'pod' in both left and right sides

What it means

Raised by the replwith() callback in Preprocessor.replace_type() while rewriting '<<lhs|rhs>>' tokens: the regex '.*pod([^m]|$)' (case-insensitive) matched the word 'pod' on BOTH sides of the '|', so the script cannot decide which side to keep. The ([^m]|$) guard exists so 'podman' does not count as 'pod'. replace_type runs on every line of every included option file (insert_file), so this fires during docs generation for any option file with an ambiguous pod|container token.

Source

Thrown at hack/markdown-preprocess:256

        Replace instances of '<<pod string|container string>>' with the
        appropriate one based on whether this is a pod-related man page
        or not.
        """
        # Internal helper function: determines the desired half of the <a|b> string
        def replwith(matchobj):
            lhs, rhs = matchobj[0].split('|')
            # Strip off '<<' and '>>'
            lhs = lhs[2:]
            rhs = rhs[:len(rhs)-2]

            # Check both sides for 'pod' followed by (non-"m" or end-of-string).
            # The non-m prevents us from triggering on 'podman', which could
            # conceivably be present in both sides. And we check for 'pod',
            # not 'container', because it's possible to have something like
            # <<container in pod|container>>.
            if re.match('.*pod([^m]|$)', lhs, re.IGNORECASE):
                if re.match('.*pod([^m]|$)', rhs, re.IGNORECASE):
                    raise Exception(f"'{matchobj[0]}' matches 'pod' in both left and right sides")
                # Only left-hand side has "pod"
                if self.pod_or_container == 'pod':
                    return lhs
                return rhs

            # 'pod' not in lhs, must be in rhs
            if not re.match('.*pod([^m]|$)', rhs, re.IGNORECASE):
                raise Exception(f"'{matchobj[0]}' does not match 'pod' in either side")
            if self.pod_or_container == 'pod':
                return rhs
            return lhs

        return re.sub(r'<<[^\|>]*\|[^\|>]*>>', replwith, line)


def main():
    "script entry point"
    script_dir = os.path.abspath(os.path.dirname(__file__))

View on GitHub (pinned to a2409076ef)

Solutions

  1. Reword so exactly one side contains 'pod' (as a word or suffix), e.g. '<<create the pod|create the container>>'
  2. If both outputs are genuinely identical and mention pods, drop the <<a|b>> construct and write the literal text

Example fix

# before
<<create the pod|delete the pod>>

# after
<<create the pod|create the container>>
Defensive patterns

Strategy: validation

Validate before calling

# Lint <<a|b>> tokens: 'pod' (not inside 'podman') must appear in exactly one half
import re, pathlib, sys
pat = re.compile(r'<<[^|>]*\|[^|>]*>>')
pod = re.compile(r'.*pod([^m]|$)', re.IGNORECASE)
bad = []
for p in pathlib.Path('docs/source/markdown/options').glob('*.md'):
    for line_no, line in enumerate(p.read_text().splitlines(), 1):
        for tok in pat.findall(line):
            lhs, rhs = tok[2:-2].split('|')
            if pod.match(lhs) and pod.match(rhs):
                bad.append(f'{p}:{line_no}: pod on both sides: {tok}')
if bad:
    sys.exit('\n'.join(bad))

Prevention

When it happens

Trigger: An options/*.md line contains something like '<<create the pod|delete the pod>>' — 'pod' (word, not 'podman') appears in both halves. Note the regex is substring-based: any text ending in 'pod' or containing 'pod' followed by a non-'m' character (e.g. 'podman-pod', 'pods') matches.

Common situations: Writing option descriptions that mention pods on both the container and pod variants; reusing 'pod' as a suffix on both sides (e.g. '<<pod create|pod kill>>'); editing shared option files used by both podman-*-pod-* and other man pages.

Related errors


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