tinyhumansai/openhuman · error · Error

provider-chain rows must be numbered 1..N in order; row ${i

Error message

provider-chain rows must be numbered 1..N in order; row ${i + 1} is numbered ${p.order}

What it means

A drift guard in parseProviderChain(): after parsing, each row's parsed order must equal its 1-based array index (orders exactly 1..N, ascending, contiguous). If row i+1 carries any other number — a duplicate, a gap, or a descending sequence — the generator throws instead of rendering a table whose Order column disagrees with reality.

Source

Thrown at scripts/generate-architecture-docs.mjs:72

        '`@generated-source:provider-chain` … `@end-source:provider-chain`'
    );
  }
  const region = appSource.slice(begin, end);
  const rowRe = /^\s*\*?\s*(\d+)\.\s+(.+?)\s+—\s+(.+?)\s*$/;
  const providers = [];
  for (const line of region.split('\n')) {
    const m = rowRe.exec(line);
    if (!m) continue;
    providers.push({ order: Number(m[1]), name: m[2].trim(), role: m[3].trim() });
  }
  if (providers.length === 0) {
    throw new Error('provider-chain source marker contained no `N. Component — role` rows');
  }
  // Guard against drift in the marker itself: orders must be 1..N, in order,
  // names non-empty, and roles free of the `|` that would break the table.
  providers.forEach((p, i) => {
    if (p.order !== i + 1) {
      throw new Error(
        `provider-chain rows must be numbered 1..N in order; row ${i + 1} is numbered ${p.order}`
      );
    }
    if (!p.name) throw new Error(`provider-chain row ${p.order} is missing a component name`);
    if (!p.role) throw new Error(`provider-chain row ${p.order} is missing a role`);
    if (p.name.includes('|') || p.role.includes('|')) {
      throw new Error(`provider-chain row ${p.order} must not contain a "|" character`);
    }
  });
  return providers;
}

/**
 * Render the markdown body that lives between the BEGIN/END markers.
 * Returned as an array of lines (no trailing join) so splicing stays
 * deterministic and line-oriented.
 *
 * @param {{ order: number, name: string, role: string }[]} providers

View on GitHub (pinned to a221052e0d)

Solutions

  1. Renumber the rows top-to-bottom as 1, 2, … N with no gaps or repeats so the numbering matches the actual chain order
  2. Prefer deleting the whole row (line) when removing a provider, then renumber the remainder
  3. Re-run `pnpm docs:generate`; the order column in gitbooks/developing/architecture/frontend.md now matches the marker

Example fix

// before — inserted PersistGate twice, numbering drifted:
 * 1. Sentry.ErrorBoundary — crash boundary
 * 2. Redux Provider — app store
 * 2. PersistGate — redux persistence
 * 4. BootCheckGate — boot gate

// after:
 * 1. Sentry.ErrorBoundary — crash boundary
 * 2. Redux Provider — app store
 * 3. PersistGate — redux persistence
 * 4. BootCheckGate — boot gate
Defensive patterns

Strategy: validation

Validate before calling

const orders = rows.map(l => Number(ROW_RE.exec(l)[1]));
const contiguous = orders.every((n, i) => n === i + 1);
if (!contiguous) {
  console.error(`Row numbering drifted: got [${orders.join(', ')}], expected 1..${orders.length}`);
  process.exit(1);
}

Prevention

When it happens

Trigger: Inserting a new provider mid-chain without renumbering (1, 2, 2, 4); deleting a middle row and leaving a gap (1, 2, 4); reordering rows physically but keeping their old numbers (1, 3, 2). Renumbering only the tail (1, 2, 5) after appending also fails.

Common situations: Any hand edit of the provider chain that touches membership or order — exactly the drift the generator exists to catch; merge conflicts resolved by taking rows from both sides without renumbering.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/fb82fd31d6e83c6b. Report an issue: GitHub.