Skip to content
← NiraNexus Home
NiraNexus

NiraNexus Log

The operational record of building a governance-first AI platform.

Log #3

How a Workaround Became the Bug

July 15, 2026·Operations·8 min read
Rakesh MaheswaranLogged by Rakesh Maheswaran, Founder, NiraNexus-OS

In brief

A custom markdown renderer processed inline code before fenced code blocks. The inline regex matched the opening and closing fence backticks as an inline pair, swallowing entire code blocks into a single <code> tag. Zero <pre> elements on the page. Every code block had a teal background. The split-based approach that caused it had been added as a workaround for Windows tool corruption. The fix: extract fenced blocks first, process inline elements second, restore fenced blocks third. Same code, different order. One gate now prevents it mechanically.

Contents


The page looked fine in development. The build passed. ESLint passed. Turbopack compiled without warnings.

On production, every code block was teal. Headings, paragraphs, entire TypeScript functions. All wrapped in a single <code> tag with a Tiffany blue background. The CSS selector .article-body code was doing exactly what it was told. The HTML was broken.

The teal bleed was first spotted during the Log #2 postmortem session. The article about fire-and-forget database writes looked fine in development. On production, the code blocks were unreadable.

Zero <pre> tags on the page. Three fenced code blocks in the markdown source. Zero in the rendered output. The inline code regex had eaten them.

Key Takeaways

  • A split-based fenced code block approach, added as a workaround for Windows tool corruption, became the root cause of a rendering bug that broke the Log for two sessions
  • The inline code regex ran before fenced block processing, matching fence backticks as an inline pair and swallowing entire code blocks into a single <code> tag
  • The diagnosis was one line: document.querySelectorAll('pre').length returned 0 for a page with three fenced code blocks
  • The fix: extract fenced blocks first, run inline processing second, restore fenced blocks third. Same code, different order. Gate 19 now verifies this mechanically.

How does a workaround become a bug?

The split-based approach was added to handle fenced code blocks. It split the HTML string on triple backticks, wrapped odd-indexed segments in <pre><code>, and joined them back together.

const segments = html.split(BACKTICK.repeat(3));
for (let i = 1; i < segments.length; i += 2) {
  segments[i] = '<pre><code>' + segments[i].trim() + '</code></pre>';
}
html = segments.join('');

No regex. No backslashes. Immune to Windows tool corruption. It worked for months.

The problem was not the approach. The problem was where it sat in the pipeline. It ran after the inline code regex had already processed the content. By the time the split looked for triple backticks, there were no triple backticks left to find.

What does the pipeline actually do, step by step?

The renderer processes markdown in a chain of regular expressions. Headings, then bold, then italic, then links, then inline code. Each step transforms the string before passing it to the next.

The inline code step uses this regex:

.replace(/`([^`]+)`/g, '<code>$1</code>')

It finds pairs of single backticks and wraps the content in <code> tags. For inline code like persistSafely(), this works correctly. It wraps the function name in a <code> tag and moves on.

The fenced code block step runs next. It splits on triple backticks and wraps the content. But the inline regex has already run. It has already found the first backtick of the opening fence and the first backtick of the closing fence as a valid pair.

The inline regex sees the opening fence's first backtick and the closing fence's first backtick as an inline pair. Everything between them becomes <code> content. The remaining backticks are not triple backticks. The split finds nothing to split on. The fenced block wrapper never fires.

Three code blocks in the source. Zero <pre> tags in the output. The .article-body code CSS selector applies a teal background to every <code> element on the page. Including the ones that now contain entire paragraphs, headings, and TypeScript functions.

The following visual represents the rendering pipeline state, reconstructed post-fix to demonstrate the structural correction.

Two-panel comparison: left shows the broken pipeline where inline regex matches fence backticks before fenced block processing, right shows the fixed pipeline where fenced blocks are extracted first using placeholders

Why wasn't it caught before production?

The build passed. ESLint has no rule for "are there <pre> tags on the deployed page." Turbopack compiled the TypeScript without errors. The CSS was correct — .article-body code { background: rgba(0, 235, 212, 0.08); } was doing exactly what it was told. The HTML was the problem, and no test checked the HTML.

The visual symptom was reported. "Teal background on headings and text." The initial diagnosis assumed a CSS specificity bug. The CSS was fine. Two sessions passed before the real question was asked: how many <pre> tags are on the page?

The answer was zero. For a page with three fenced code blocks. That single number redirected the entire investigation from CSS to the rendering pipeline. The document.querySelectorAll('pre').length check took less than a second. It had been available the entire time.

The markdown-it parsing pipeline documents this as an architectural invariant: block parsing happens first, then inline parsing. The custom renderer had inverted that order. It was not a bug in the regex. It was a bug in the sequence.

What's the fix, and why is it just an order change?

The fix does not change what the code does. It changes when it does it.

// Step 1: Extract fenced blocks FIRST — before any inline processing
const FENCE = String.fromCharCode(96).repeat(3);
const fencedBlocks = [];
let processed = content.replace(
  new RegExp(FENCE + '[^\\n]*\\n([\\s\\S]*?)' + FENCE, 'g'),
  (_, code) => {
    fencedBlocks.push(code.trimEnd());
    return '\x00FENCED' + (fencedBlocks.length - 1) + '\x00';
  }
);

// Step 2: Run ALL inline processing on placeholder-ized content
let html = processed
  .replace(/`([^`]+)`/g, '<code>$1</code>')
  // ... all other inline processing ...

// Step 3: Restore fenced blocks as <pre><code>
html = html.replace(
  /\x00FENCED(\d+)\x00/g,
  (_, idx) => '<pre><code>' + fencedBlocks[idx] + '</code></pre>'
);

The fenced blocks are extracted into an array before the inline regex chain touches them. They are replaced with NUL-byte placeholders that no regex will match. The inline chain processes the clean content. The fenced blocks are restored as proper <pre><code> elements.

Same inline code regex. Same fenced block wrapper. Different order. The split-based approach was not wrong. It was in the wrong position. The workaround had been running after the code it was supposed to protect.

Python-Markdown issue #1492 asks the exact same question: "inline patterns run before block processors?" The answer in every proper markdown parser is no. Blocks first, inline second. The custom renderer had violated that invariant. The QuantumRAG project applied an identical fix three months later — extract into placeholders, process inline, restore as blocks. Independent reproduction, same root cause, same solution.

What gate now prevents this?

Gate 19 in the pre-code gate pipeline now verifies that fenced code blocks produce <pre> tags. It runs on every commit. It catches the pattern before a deployment leaves the machine.

The check is mechanical. It does not inspect the renderer code or validate the regex. It asks one question: does the deployed page contain the expected number of <pre> elements? If the count is zero and the source has fenced blocks, the build fails.

This gate would have caught the bug before it reached production. The CSS was never the problem. The regex was never the problem. The order was the problem. Gate 19 verifies the output, not the implementation.

The workaround was added to solve a real problem. It solved it. Then it became a new problem. The fix was not removing the workaround. It was moving it to the correct position in the pipeline. Same code. Different order. One gate to make sure it stays there.

Log #1 described how the adversarial pipeline works. Log #2 documented what broke when the plumbing failed. This log documents what broke when a past fix became the failure itself. Three Operations pieces. Three layers of infrastructure hardening.

The pipelines are hardened. The next layer is the governance system that enforces them — the mechanical rules, the tracker updates, the gates that fire before a commit leaves the machine. That is Log #4.

FAQ

Why did the inline regex match fence backticks?

The regex looked for pairs of single backticks. The first backtick of the opening fence and the first backtick of the closing fence formed a valid pair. Everything between them — the language tag, the entire code block — became inline <code> content. The remaining backticks were not triple backticks, so the fenced block split never fired.

Why wasn't this caught before production?

The build passed. ESLint passed. The CSS was correct. No test checked whether the deployed page contained <pre> tags. The visual symptom was reported twice before the right question was asked: how many <pre> elements are actually on the page? The answer was zero.

What prevents this from happening again?

Gate 19 verifies that fenced code blocks produce <pre> tags. It runs on every commit. It catches the pattern mechanically. The check does not inspect the renderer code — it verifies the output.

Why is order the problem, not the code?

The split-based approach worked correctly in isolation. It failed because it ran after the inline regex had already corrupted the fence backticks. The fix does not change what the code does. It changes when it does it. Extract first. Process inline second. Restore third.

How a Workaround Became the Bug — NiraNexus Log