{"record":{"id":"e1257b9951479e85","repo":"mermaid-js/mermaid","slug":"start-should-have-been-set-during-first-phase","errorCode":null,"errorMessage":"start should have been set during first phase","messagePattern":"start should have been set during first phase","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mermaid/src/diagrams/packet/parser.ts","lineNumber":61,"sourceCode":"        word = [];\n        row++;\n      }\n      if (!nextBlock) {\n        break;\n      }\n      ({ start, end, bits, label } = nextBlock);\n    }\n  }\n  db.pushWord(word);\n};\n\nconst getNextFittingBlock = (\n  block: PacketBlock,\n  row: number,\n  bitsPerRow: number\n): [Required<PacketBlock>, PacketBlock | undefined] => {\n  if (block.start === undefined) {\n    throw new Error('start should have been set during first phase');\n  }\n  if (block.end === undefined) {\n    throw new Error('end should have been set during first phase');\n  }\n\n  if (block.start > block.end) {\n    throw new Error(`Block start ${block.start} is greater than block end ${block.end}.`);\n  }\n\n  if (block.end + 1 <= row * bitsPerRow) {\n    return [block as Required<PacketBlock>, undefined];\n  }\n\n  const rowEnd = row * bitsPerRow - 1;\n  const rowStart = row * bitsPerRow;\n  return [\n    {\n      start: block.start,","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/mermaid-js/mermaid/blob/d93e9c88c01a599c062ee6a3f1462e3558ac6b90/packages/mermaid/src/diagrams/packet/parser.ts#L43-L79","documentation":"Thrown by getNextFittingBlock when block.start is undefined. The populate loop's first phase is supposed to assign start (either from the AST or defaulted to lastBit+1) before ever calling getNextFittingBlock, so an undefined start here means an internal invariant was violated. It is not reachable through valid user input — the contiguity and end<start guards run first.","triggerScenarios":"An internal bug where the block object passed into getNextFittingBlock lost its start field; programmatic construction of a PacketBlock with start omitted and fed directly to the layout; a regression in the populate loop's variable rebinding (the ({ start, end, bits, label } = nextBlock) destructure).","commonSituations":"Appears only after internal mermaid changes or custom forks; not triggerable from packet-beta text syntax in released versions.","solutions":["Report upstream as a mermaid bug with the reproducing packet-beta input and version.","Upgrade to the latest mermaid release.","If calling getNextFittingBlock directly in a fork, ensure start and end are always set on the block before invocation.","Audit the destructure rebinding at the loop tail to confirm nextBlock always carries start."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function blockHasStart(block: {start?:number}): block is {start:number} {\n  return block.start !== undefined;\n}","tryCatchPattern":"try {\n  await mermaid.parse(text);\n} catch (e) {\n  if (e instanceof Error && /start should have been set during first phase/.test(e.message)) {\n    // internal invariant — report upstream\n    reportBug(e, text);\n  } else throw e;\n}","preventionTips":["Report this internal-invariant throw upstream with a reproducer.","If forking, always set start on PacketBlock before calling getNextFittingBlock.","Keep mermaid updated."],"tags":["mermaid","packet","parsing","internal-invariant"],"backgroundTag":null,"analyzedSha":"d93e9c88c01a599c062ee6a3f1462e3558ac6b90","analyzedAt":"2026-08-12T06:23:11.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}