tinyhumansai/openhuman · error · Error
provider-chain source marker not found in App.tsx; expected
Error message
provider-chain source marker not found in App.tsx; expected `@generated-source:provider-chain` … `@end-source:provider-chain`
What it means
Thrown by parseProviderChain() in the docs generator (issue #3892 slice) when app/src/App.tsx no longer contains a valid source-of-truth marker block. The generator derives the documented frontend provider chain from the comment between the literal markers `@generated-source:provider-chain` and `@end-source:provider-chain`; if either marker string is absent (indexOf === -1) or the end marker appears before the begin marker, it refuses to run rather than emit an empty table.
Source
Thrown at scripts/generate-architecture-docs.mjs:52
export const FRONTEND_DOC = resolve(REPO_ROOT, 'gitbooks/developing/architecture/frontend.md');
/** Stable tokens used to locate the generated block in the doc. */
const BLOCK_BEGIN_TOKEN = 'BEGIN GENERATED: provider-chain';
const BLOCK_END_TOKEN = 'END GENERATED: provider-chain';
/**
* Parse the ordered provider chain out of the `@generated-source:provider-chain`
* marker block in App.tsx source text.
*
* @param {string} appSource - contents of App.tsx
* @returns {{ order: number, name: string, role: string }[]}
* @throws if the marker block is missing, empty, or rows are malformed / non-contiguous
*/
export function parseProviderChain(appSource) {
const begin = appSource.indexOf('@generated-source:provider-chain');
const end = appSource.indexOf('@end-source:provider-chain');
if (begin === -1 || end === -1 || end < begin) {
throw new Error(
'provider-chain source marker not found in App.tsx; expected ' +
'`@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) => {View on GitHub (pinned to a221052e0d)
Solutions
- Recover the marker block with `git log -p -- app/src/App.tsx` and restore it verbatim between `@generated-source:provider-chain` and `@end-source:provider-chain`, keeping the `N. Component — role` rows
- Check the marker spellings character-by-character — both are literal indexOf matches; a renamed or misspelled marker is invisible to the parser
- Confirm the end marker sits BELOW the begin marker inside the same comment block
- Re-run `pnpm docs:generate` then `pnpm docs:check` to confirm the drift gate passes
Example fix
// before — App.tsx comment block edited, markers gone: /* * Provider chain: Sentry -> Redux -> PersistGate ... */ // after — markers restored as the parseable source of truth: /* * @generated-source:provider-chain * 1. Sentry.ErrorBoundary — global crash boundary * 2. Redux Provider — app-wide store * ... * @end-source:provider-chain */
Defensive patterns
Strategy: validation
Validate before calling
// Preflight before pnpm docs:generate / docs:check
import { readFileSync } from 'node:fs';
const src = readFileSync('app/src/App.tsx', 'utf8');
const begin = src.indexOf('@generated-source:provider-chain');
const end = src.indexOf('@end-source:provider-chain');
if (begin === -1 || end === -1 || end < begin) {
console.error(`App.tsx marker check failed: begin=${begin} end=${end} — restore the marker block first`);
process.exit(1);
} Try / catch
try {
const { updated, current } = computeFrontendDoc();
} catch (err) {
if (err.message.includes('source marker not found')) {
console.error('App.tsx lost its @generated-source:provider-chain block — recover it with `git log -p -- app/src/App.tsx`');
process.exitCode = 1;
} else throw err;
} Prevention
- Treat the marker block in App.tsx as load-bearing generated-source metadata, not a disposable comment — mention it in PR review when App.tsx diff touches comments
- Keep `pnpm docs:check` (Docs Drift lane) green so marker damage surfaces in CI, not at the next docs regen
- When relocating the provider chain, move the marker block with it and re-run docs:generate in the same PR
When it happens
Trigger: Running `node scripts/generate-architecture-docs.mjs` (or `pnpm docs:generate` / `pnpm docs:check`) after the marker comment block in App.tsx was deleted, reworded (e.g. `@generated-source:providers`), or the two marker lines were reordered so `@end-source:provider-chain` precedes `@generated-source:provider-chain`. Also hit if APP_TSX resolves to a file that is not the real app/src/App.tsx.
Common situations: Refactoring the provider chain in App.tsx and rewriting/stripping the surrounding block comment; IDE 'clean up comments' or a lint rule removing what looks like a dead comment; hand-merging a conflict that drops the marker lines.
Related errors
- provider-chain rows must be numbered 1..N in order; row ${i
- generated-block markers not found in ${FRONTEND_DOC}; expect
- provider-chain source marker contained no `N. Component — ro
- provider-chain row ${p.order} is missing a component name
- provider-chain row ${p.order} must not contain a "|" charact
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/f846091853bb5e15.
Report an issue: GitHub.