mermaid-js/mermaid · error · Error

Packet block - is not contiguous. It should start from .

Error message

Packet block ${start} - ${end ?? start} is not contiguous. It should start from ${lastBit + 1}.

What it means

Thrown by the packet populate loop when a block's start does not equal lastBit+1, i.e. the block leaves a gap or overlaps the previous block. Packet layouts must be contiguous: each block must begin exactly where the previous one ended. The error message reports the expected starting bit so the author can fix the offset.

Solutions

  1. Make each block start exactly at the previous block's end+1; the error message tells you the expected value.
  2. Omit start on non-first blocks to let mermaid auto-continue from lastBit+1.
  3. For intentional gaps, insert an unnamed block covering the reserved bits.
  4. Lay out fields sequentially from bit 0 without skipping.

Example fix

// before — gap between blocks
packet-beta
  0-7: Field A
  16-23: Field B   // gap at 8-15

// after — contiguous, or omit start
packet-beta
  0-7: Field A
  8-15: Reserved
  16-23: Field B
Defensive patterns

Strategy: validation

Validate before calling

// Validate packet contiguity before render.
function validateContiguity(blocks: {start?:number;end?:number;bits?:number}[]): string[] {
  const errors: string[] = [];
  let lastBit = -1;
  for (const b of blocks) {
    const start = b.start ?? lastBit + 1;
    if (start !== lastBit + 1) {
      errors.push(`Block starting at ${start} is not contiguous (expected ${lastBit + 1})`);
    }
    const end = b.end ?? start + (b.bits ?? 1) - 1;
    lastBit = end;
  }
  return errors;
}

Try / catch

try {
  await mermaid.render('g', diagramText);
} catch (e) {
  if (e instanceof Error && /is not contiguous/.test(e.message)) {
    showUserError('Packet blocks must be contiguous with no gaps or overlaps. The error message names the expected start bit.');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Declaring a block with start greater than lastBit+1 (a gap); declaring start less than lastBit+1 (an overlap); providing only start on a non-first block where it doesn't continue from the previous end.

Common situations: Hand-authoring a packet field layout and losing count of bit positions; leaving intentional gaps (unsupported — use reserved/empty blocks instead); renumbering fields without updating subsequent starts.

Related errors


AI-assisted analysis of mermaid-js/mermaid@d93e9c88c0 (2026-08-12). Data as JSON: /api/errors/4e14a998deec52c5. Report an issue: GitHub.

Appendix: source

Thrown at packages/mermaid/src/diagrams/packet/parser.ts:24

import { PacketDB } from './db.js';
import type { PacketBlock, PacketWord } from './types.js';

const maxPacketSize = 10_000;

const populate = (ast: Packet, db: PacketDB) => {
  populateCommonDb(ast, db);
  let lastBit = -1;
  let word: PacketWord = [];
  let row = 1;
  const { bitsPerRow } = db.getConfig();

  for (let { start, end, bits, label } of ast.blocks) {
    if (start !== undefined && end !== undefined && end < start) {
      throw new Error(`Packet block ${start} - ${end} is invalid. End must be greater than start.`);
    }
    start ??= lastBit + 1;
    if (start !== lastBit + 1) {
      throw new Error(
        `Packet block ${start} - ${end ?? start} is not contiguous. It should start from ${
          lastBit + 1
        }.`
      );
    }
    if (bits === 0) {
      throw new Error(`Packet block ${start} is invalid. Cannot have a zero bit field.`);
    }
    end ??= start + (bits ?? 1) - 1;
    bits ??= end - start + 1;
    lastBit = end;
    log.debug(`Packet block ${start} - ${lastBit} with label ${label}`);

    while (word.length <= bitsPerRow + 1 && db.getPacket().length < maxPacketSize) {
      const [block, nextBlock] = getNextFittingBlock({ start, end, bits, label }, row, bitsPerRow);
      word.push(block);
      if (block.end + 1 === row * bitsPerRow) {
        db.pushWord(word);

View on GitHub (pinned to d93e9c88c0)