How DESIGN.md Handles Duplicate Section Headings and What Error Is Produced

DESIGN.md's CLI linter throws a fatal "Duplicate top-level sections detected" error and aborts with a non-zero exit code when it encounters two identical level-one headings.

The google-labs-code/design.md repository provides a strict specification format for design documents, enforced by a dedicated CLI tool. When validating a DESIGN.md file, the linter parses the document into blocks and specifically monitors all top-level headings to ensure each title appears exactly once. This duplicate detection mechanism prevents ambiguous document structures and maintains a clear hierarchy for design specifications.

Duplicate Section Detection Logic

The linter implements a single-pass validation algorithm that tracks encountered headings using an in-memory Set. This approach ensures O(1) lookup time for duplicate checks while parsing the document stream.

How the Parser Identifies Top-Level Headings

During the parsing phase in packages/cli/src/linter/parser/handler.ts, the linter iterates through all document blocks and filters for markdown headings with a depth of exactly one. The parser inspects each block's type and depth properties, extracting the trimmed title string only from level-one headings (those starting with a single #).

The detection logic specifically checks for block.type === 'heading' && block.depth === 1 before adding the title to the tracking Set. This ensures that duplicate H2 or H3 headings do not trigger the validation error, as the specification only requires uniqueness at the top level.

The Duplicate Check Implementation

The core validation occurs within the parsing handler, where the linter maintains a seen Set to record previously encountered titles. When a duplicate is detected, the parser immediately throws an Error with the specific heading title included in the message.

// Simplified excerpt from packages/cli/src/linter/parser/handler.ts
function collectTopLevelSections(blocks: Block[]) {
  const seen = new Set<string>();
  for (const block of blocks) {
    if (block.type === 'heading' && block.depth === 1) {
      const title = block.title.trim();
      if (seen.has(title)) {
        // ← Duplicate heading found → throw the error
        throw new Error(
          `Duplicate top-level sections detected: "${title}"`
        );
      }
      seen.add(title);
    }
  }
}

This implementation treats duplicate top-level headings as a fatal parsing error, meaning the linter stops immediately rather than collecting multiple validation issues.

The Error Message and CLI Behavior

When the linter detects a duplicate, it produces a specific error message format that includes the exact heading text in quotation marks. The error propagates up through the call stack and terminates the CLI process.

A typical error output appears as follows:


Error: Duplicate top-level sections detected: "Overview"
    at /packages/cli/src/linter/parser/handler.ts:161

The stack trace points to the specific line in handler.ts (approximately line 161 in the current version) where the duplicate check executes. Because the linter treats this as a fatal condition, the CLI exits with a non-zero exit code, causing any CI step that runs design.md lint to fail immediately.

Running the linter on a file containing two # Overview headings demonstrates this behavior:

$ design.md lint ./examples/design/DESIGN.md
Error: Duplicate top-level sections detected: "Overview"
    at /packages/cli/src/linter/parser/handler.ts:161

Files Involved in the Validation Pipeline

Three key files comprise the duplicate detection and error reporting pipeline:

Summary

  • DESIGN.md's linter validates that all level-one headings (H1) have unique titles using a Set-based tracking mechanism.
  • The parser in handler.ts throws a fatal error with the message Duplicate top-level sections detected: "<title>" immediately upon finding a duplicate.
  • This error causes the CLI to exit with a non-zero status code, failing CI pipelines that enforce DESIGN.md validation.
  • Only top-level headings trigger this validation; duplicate H2 and H3 headings are permitted.

Frequently Asked Questions

Does DESIGN.md allow duplicate H2 or H3 headings?

Yes. The duplicate section validation only applies to top-level headings (H1, where block.depth === 1). The linter explicitly checks the depth property before running the duplicate detection, so multiple identical H2 (##) or H3 (###) headings within different sections will not trigger the error.

What exit code does the CLI return when detecting duplicate headings?

The CLI returns a non-zero exit code when it encounters duplicate top-level sections. Because the parser throws an uncaught Error in collectTopLevelSections, the error propagates to the top-level command handler in packages/cli/src/commands/lint.ts, which terminates the process with a failure status suitable for CI/CD pipelines.

Can the linter report multiple duplicate headings in one run?

No. The current implementation treats duplicate top-level sections as a fatal error, meaning the linter aborts immediately upon finding the first duplicate. The parser throws an Error at line ~161 in handler.ts before completing the document traversal, so subsequent duplicates (or other validation issues) will not be reported in that run.

How does the error message identify which heading is duplicated?

The error message includes the exact heading title inside quotation marks. Specifically, the thrown Error uses the template: Duplicate top-level sections detected: "${title}", where ${title} is the trimmed text content of the duplicate H1 heading. This allows developers to quickly locate the problematic section in their document.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →