Skip to content
NLEN
Illustration: Steering Markdown Tables and Nested Lists

Consistently Steering Markdown Tables and Nested Lists

By Ivo Donker — compiled with AI assistance (Claude & Gemini) · August 23, 2026

When a language model needs to present textual data for human readability or direct display in web interfaces, Markdown is almost always the preferred format. Compared to strictly typed payload formats such as JSON, where parsers crash hard on a missing comma or missing closing bracket, Markdown fails in a much subtler and visually disruptive way. Rows suddenly lose a column, unescaped separator characters within field text break table grids completely, and indentation in hierarchical lists shifts unpredictably between two spaces, four spaces, and tab characters. The result is that CommonMark and GitHub Flavored Markdown (GFM) engines render the generated text mangled or as unformatted plain paragraphs.

In this in-depth technical article, we examine how to gain full deterministic control over Markdown output. We dive into the underlying tokenization mechanisms that drive syntax corruption, discuss proven prompt patterns for complex multi-layered structures, cover edge cases and measurable evaluation methods, and explain the cost and processing trade-offs of prompt-driven document formatting.

The anatomy of syntax corruption in GFM tables

A conformant GFM table imposes strict requirements on the alignment of pipes (|) and the presence of a valid separator line (|---|). Autoregressive language models, however, generate text token by token from left to right. While generating cell 4 on row 18, the model has no active memory access to the header row's column count unless the attention mechanism explicitly picks this up from the preceding context stream. As soon as cell content dynamically grows longer or contains unexpected punctuation, structural shifts occur.

The most frequent cause of table corruption is the unescaped pipe within cell content. When a model writes out a code snippet, a regular expression, or a logical operation (such as a || b or a Linux pipeline), a standard Markdown parser interprets that pipe character directly as a column separator. This shifts all subsequent cells within that row one position to the right. The row suddenly has one column too many, and the visual table layout falls apart completely. To fix this structurally, explicit rules must be given about escaping pipes via \| or consistently wrapping inline code within backticks.

A second persistent problem is omitting the outer pipes or generating mismatched separator lines. Although permissive parsers sometimes tolerate rows without a leading or trailing pipe, strict renderers fail when the separator line contains fewer than three hyphens per cell or when alignment colons are placed incorrectly. For deeper instruction strategies, refer to the guide on enforcing form from within the prompt itself, which explains how to dictate token order through rigid frameworks.

Indentation and hierarchy in deeply nested lists

When building taxonomic trees, directory overviews, or multi-layered step plans, whitespace management is the biggest failure factor. According to the CommonMark specification, a nested list requires exact and consistent indentation relative to the parent item. As soon as a language model mixes two spaces with four spaces, a serious parsing error occurs: the parser does not interpret a four-space indentation as a sublist, but as an indented code block, and wraps the text in a <pre>container.

This behavior follows directly from how tokenizers handle whitespace. Widely used tokenizers (such as cl100k_base or newer variants) have specific tokens for combinations such as two spaces, four spaces, a tab, or a line break followed by spaces. During complex reasoning, the model does not always choose the uniform token sequence for indentation, which lets small variations creep in. Without strict format restrictions, this leads to unwanted visual jumps and broken list numbering.

Construction Typical failure mode Cause in the token stream Mitigation strategy in the prompt
Markdown table Inconsistent number of columns per row Pipes inside data split cells unintentionally Escape pipes as \| or put cells in backticks
Table separator line Table renders as plain text Fewer than 3 hyphens per column cell Dictate a fixed template: |---|---|
Nested list (level 2+) Sub-item renders as a <pre> code block Indentation jump from 2 to 4+ spaces Uniform rule: exactly 2 spaces per depth level
Mixed nested lists Numbering spontaneously resets to 1 Blank line between parent item and sublist Strictly forbid blank lines within the same list branch
Long cell text in tables Hard line breaks split the table row Model generates \n inside a cell value Forbid line breaks; use <br> or commas

Prompt techniques for deterministic table structures

To get a model to reliably produce correct Markdown tables, a general instruction such as "present the result in a table" is nowhere near enough. The prompt has to impose formal structural constraints: the exact number of columns, the separator pattern, the mandatory presence of edge pipes, and a fixed fallback value for missing data.

Below is a proven prompt template designed to minimize syntactic deviations. We specify both the visual skeleton and the rules for field handling:

### INSTRUCTIE VOOR TABELFORMAAT:
Genereer de output als een strikte GitHub Flavored Markdown (GFM) tabel.
Volg exact de onderstaande formele syntaxis:

| Parameter | Type | Standaardwaarde | Beschrijving |
|---|---|---|---|
| max_tokens | integer | 2048 | Maximale lengte van de gegenereerde respons |
| temperature | float | 0.7 | Mate van willekeur in tokenkeuze |

Syntactische regels:
1. Elke rij MOET beginnen met een "|" en eindigen met een "|".
2. De scheidingsregel (header delimiter) MOET exact het formaat "|---|---|---|---|" hanteren.
3. Bevat een cel geen data? Vul deze dan altijd met "N/B" of "-" (laat cellen nooit leeg).
4. Verboden: harde regeleindes of ongeëscapete pipes binnen een cel. Schrijf pipes in tekst als "\|".
5. Alle codefragmenten of variabelen binnen een cel MOETEN tussen backticks (`...`) staan.
6. Voeg geen inleidende of afsluitende tekst toe buiten het tabelblok.

When the source data is complex or has to be extracted from large unstructured documents, the choice of model has a direct influence on parsing stability. Consult the overview of choosing models for data extraction from tables and CSV to determine which LLM architectures perform most reliably on column-based data processing.

Steering tree structures and nested lists

When generating hierarchical data (such as categorizations, decision trees, or navigation structures), it is essential to define the number of depth levels and the indentation convention explicitly. Without those boundaries, language models tend to nest too deeply, which makes the structure unreadable on mobile screens and causes renderers to bog down in complex DOM trees.

The most stable configuration for nested lists uses strict indentation of exactly two spaces per level, combined with alternating bullet symbols per depth level. This forces the model into a clear token distinction between top-level topics and subordinate levels:

### INSTRUCTIE VOOR GENESTE LIJSTEN:
Structureer de categorisatie volgens onderstaande hiërarchische conventie:

- Hoofdcategorie A
  * Subcategorie A1 (exact 2 spaties inspringing)
    + Detailniveau A1a (exact 4 spaties inspringing)
    + Detailniveau A1b (exact 4 spaties inspringing)
  * Subcategorie A2 (exact 2 spaties inspringing)
- Hoofdcategorie B
  * Subcategorie B1 (exact 2 spaties inspringing)

Regels voor de lijststructuur:
1. Gebruik nooit tabs; gebruik uitsluitend spaties voor indentatie.
2. Plaats GEEN lege regels tussen een hoofditem en de bijbehorende geneste sub-items.
3. Beperk de diepte tot maximaal 3 niveaus.
4. Gebruik voor niveau 1 '-', voor niveau 2 '*', en voor niveau 3 '+'.

By stating negative restrictions explicitly, such as forbidding blank lines between nested elements, you prevent the Markdown parser from opening a new paragraph block and splitting the list hierarchically. For a deeper exploration of exclusion mechanisms, see the article on negative prompting and constraint enforcement.

Edge cases and rare failure modes

Beyond the standard situations, specific edge cases occur in production that can circumvent regular prompt instructions. Recognizing these patterns lets developers draw up targeted defensive rules.

A persistent edge case arises with cell values that contain Markdown formatting characters, such as asterisks for bold text (**waarde**) or hyperlinks. When a link contains a pipe or brackets that are not properly closed, the parser loses track. Another problem arises with cell text containing HTML tags (such as <span> or unfiltered user input). On encountering an HTML tag, some Markdown engines switch to raw HTML block parsing, which causes the surrounding GFM table structure to be ignored entirely.

With nested numbered lists, a "number reset" frequently occurs when a nested item contains a longer explanation of several sentences. If the model inserts a line break without the correct indentation of four spaces on the continuation line, the CommonMark parser sees the next numbered item as an entirely new list and restarts the count at 1. This calls for an explicit instruction that every list item must consist of exactly one uninterrupted line of text.

Comparison: Markdown tables versus alternative structures

Although Markdown is compact and immediately readable, it has operational limitations compared with machine-oriented data formats. In architectures where data is processed automatically downstream, a careful trade-off has to be made between human readability and parser reliability.

Property Markdown table JSON schema (structured output) HTML table (<table>)
Token Efficiency Very high (minimal syntactic overhead) Medium (repetitive key names and quotes) Low (many opening and closing tags)
Parser robustness Moderate (vulnerable to delimiter errors) 100% deterministic with constrained decoding High (tolerant DOM parsers)
Support for nested data None (does not support cells with subtables) Full (unlimited nested arrays and objects) Possible (nested tables are complex)
Direct human readability Excellent in documents, chat, and terminals Low (requires rendering or visualization) Poor in plain text
API compatibility Requires regular expressions or a GFM parser Directly readable through json.loads() Requires an HTML parser such as BeautifulSoup

When the generated data serves only for further backend processing and is not shown directly to a user, an enforced JSON schema through the model API offers considerably more operational certainty. Consult the overview of enforcing output through prompt rules or an API schema to determine when prompt-based Markdown is enough and when JSON schemas are necessary.

Measurement method and evaluation of parsability

To monitor the quality of Markdown generation systematically across different model versions and prompt iterations, an automated measurement method is essential. A reliable validation test measures not only whether a table is present, but tests the output against four quantifiable criteria:

  1. Symmetry index (column uniformity): The percentage of rows in which the number of columns matches the header row exactly. In a healthy pipeline this should be 100%.
  2. Delimiter conformity: A check on the validity of line 2. Does every column contain at least three hyphens, and are optional alignment colons placed correctly?
  3. Escape integrity: Detection of unescaped pipe characters inside cell strings that are not enclosed in code backticks.
  4. Indentation consistency (for lists): A check on whether all sublists use a multiple of exactly 2 spaces without unexpected tabs or irregular jumps.

By including these checks in an automated evaluation set with at least 100 representative prompts, a team can immediately establish whether a prompt change causes a regression in structural reliability.

Automated validation and recovery strategies

Despite rigorous prompt instructions, a language model can occasionally produce syntax errors under heavy context load, latency spikes, or extreme token limits. In production environments you therefore implement a validation layer directly after the model call.

When the validation tool detects a deviation (for example: "Row 5 has 3 columns instead of 4"), the corrupted output is sent back to the model together with the specific parser error in a targeted recovery step. How to configure such an automated self-healing loop and integrate it into your backend is described step by step in the article on recovery prompts for failed validation of LLM output.

Implementation example: a Python validator for GFM tables

Below is a complete, robust parser function that checks whether a generated Markdown string contains a valid table structure. The code checks symmetry, delimiters, and disallowed punctuation:

def valideer_markdown_tabel(markdown_tekst: str) -> dict:
    regels = [r.strip() for r in markdown_tekst.strip().split('\n') if r.strip()]
    tabel_regels = [r for r in regels if r.startswith('|') and r.endswith('|')]
    
    if len(tabel_regels) < 3:
        return {"valide": False, "fout": "Onvoldoende rijen voor een conforme tabel (minimaal header, delimiter en 1 datarow vereist)."}
        
    def splits_rij(rij: str) -> list[str]:
        # Verwijder begin- en eindpipe en splits op niet-geëscapete pipes
        inhoud = rij[1:-1]
        cellen = []
        huidige_cel = []
        ontsnapt = False
        in_code = False
        
        for char in inhoud:
            if char == '\\' and not ontsnapt:
                ontsnapt = True
                huidige_cel.append(char)
            elif char == '`' and not ontsnapt:
                in_code = not in_code
                huidige_cel.append(char)
            elif char == '|' and not ontsnapt and not in_code:
                cellen.append(''.join(huidige_cel).strip())
                huidige_cel = []
            else:
                ontsnapt = False
                huidige_cel.append(char)
                
        cellen.append(''.join(huidige_cel).strip())
        return cellen
        
    header_cellen = splits_rij(tabel_regels[0])
    aantal_kolommen = len(header_cellen)
    
    # Controleer delimiterrij (rij index 1)
    delimiter_cellen = splits_rij(tabel_regels[1])
    if len(delimiter_cellen) != aantal_kolommen:
        return {"valide": False, "fout": f"Delimiterrij telt {len(delimiter_cellen)} kolommen, verwacht {aantal_kolommen}."}
        
    for cel in delimiter_cellen:
        schone_cel = cel.replace(':', '').strip()
        if not set(cel).issubset({'-', ':', ' '}) or len(schone_cel) < 3:
            return {"valide": False, "fout": f"Ongeldig delimiterpatroon: '{cel}'. Minimaal 3 koppeltekens vereist."}
            
    # Controleer datarijen
    for idx, rij in enumerate(tabel_regels[2:], start=3):
        cellen = splits_rij(rij)
        if len(cellen) != aantal_kolommen:
            return {
                "valide": False, 
                "fout": f"Rij {idx} heeft {len(cellen)} kolommen; verwacht {aantal_kolommen}."
            }
            
    return {"valide": True, "kolommen": aantal_kolommen, "rijen": len(tabel_regels) - 2}

This validation function performs a full integrity check within fractions of a millisecond before the data is sent to a storage medium or frontend.

Token costs and operational trade-offs

Using Markdown tables has a direct effect on token consumption and processing time (latency). Compared with compact CSV output, a Markdown table introduces formatting tokens for pipes, spaces, and the separator line. In a table of 50 rows with 5 columns, the separator line alone accounts for roughly 20 to 30 tokens, while the repeated pipes and spaces add another 150 to 200 tokens to the output stream.

Compared with JSON, on the other hand, Markdown is often 20% to 40% more economical in tokens, because JSON has to repeat the field names (keys) for every object. That makes Markdown a cost-efficient choice for tabular data intended primarily for human consumption. The risk of parsing errors does mean you have to account for the potential cost of retry calls: when 5% of generated tables have to be requested again because of a syntax error, that offsets part of the token saving.

Conclusion and best practices

Markdown tables and hierarchical lists form a powerful bridge between structured data and attractive human presentation. By providing the language model with an unambiguous syntactic skeleton, formal rules for special characters, and explicit negative restrictions, the reliability of the output can be raised considerably.

In a mature production environment, these prompt instructions are combined with a lightweight local validator and an automated recovery route. That preserves the speed and token efficiency of Markdown without giving up the structural robustness modern software applications require.