Fission-AI/OpenSpec · error · Error

Change must have a Why section

Error message

Change must have a Why section

What it means

Thrown by parseChangeWithDeltas when the change document's 'Why' section is missing or empty. Structural validation of proposal.md: every change must explain its motivation, so parsing fails early rather than archiving an unexplained change; input at fault is the change markdown lacking a populated Why heading.

Solutions

  1. Add a '## Why' section to the change markdown explaining the motivation
  2. Check the heading spelling and heading level (##)
  3. Ensure the section body is non-empty
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/core/parsers/change-parser.ts:28 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Fission-AI/OpenSpec@6926ccb18a (2026-08-25). Data as JSON: /api/errors/18fd289341351a8a. Report an issue: GitHub.

Appendix: source

Thrown at src/core/parsers/change-parser.ts:28

  requirements: Requirement[];
  renames?: Array<{ from: string; to: string }>;
}

export class ChangeParser extends MarkdownParser {
  private changeDir: string;

  constructor(content: string, changeDir: string) {
    super(content);
    this.changeDir = changeDir;
  }

  async parseChangeWithDeltas(name: string): Promise<Change> {
    const sections = this.parseSections();
    const why = this.findSection(sections, 'Why')?.content || '';
    const whatChanges = this.findSection(sections, 'What Changes')?.content || '';
    
    if (!why) {
      throw new Error('Change must have a Why section');
    }
    
    if (!whatChanges) {
      throw new Error('Change must have a What Changes section');
    }

    // Parse deltas from the What Changes section (simple format)
    const simpleDeltas = this.parseDeltas(whatChanges);
    
    // Check if there are spec files with delta format
    const specsDir = path.join(this.changeDir, 'specs');
    const deltaDeltas = await this.parseDeltaSpecs(specsDir);
    
    // Combine both types of deltas, preferring delta format if available
    const deltas = deltaDeltas.length > 0 ? deltaDeltas : simpleDeltas;

    return {
      name,

View on GitHub (pinned to 6926ccb18a)