{"record":{"id":"c0213bf367978024","repo":"tinyhumansai/openhuman","slug":"provider-chain-row-p-order-must-not-contain-a","errorCode":null,"errorMessage":"provider-chain row ${p.order} must not contain a \"|\" character","messagePattern":"provider-chain row (.+?) must not contain a \"\\|\" character","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/generate-architecture-docs.mjs","lineNumber":79,"sourceCode":"    const m = rowRe.exec(line);\n    if (!m) continue;\n    providers.push({ order: Number(m[1]), name: m[2].trim(), role: m[3].trim() });\n  }\n  if (providers.length === 0) {\n    throw new Error('provider-chain source marker contained no `N. Component — role` rows');\n  }\n  // Guard against drift in the marker itself: orders must be 1..N, in order,\n  // names non-empty, and roles free of the `|` that would break the table.\n  providers.forEach((p, i) => {\n    if (p.order !== i + 1) {\n      throw new Error(\n        `provider-chain rows must be numbered 1..N in order; row ${i + 1} is numbered ${p.order}`\n      );\n    }\n    if (!p.name) throw new Error(`provider-chain row ${p.order} is missing a component name`);\n    if (!p.role) throw new Error(`provider-chain row ${p.order} is missing a role`);\n    if (p.name.includes('|') || p.role.includes('|')) {\n      throw new Error(`provider-chain row ${p.order} must not contain a \"|\" character`);\n    }\n  });\n  return providers;\n}\n\n/**\n * Render the markdown body that lives between the BEGIN/END markers.\n * Returned as an array of lines (no trailing join) so splicing stays\n * deterministic and line-oriented.\n *\n * @param {{ order: number, name: string, role: string }[]} providers\n * @returns {string[]}\n */\nexport function renderProviderChainBody(providers) {\n  return [\n    '',\n    '_Generated from `app/src/App.tsx` by `scripts/generate-architecture-docs.mjs`. ' +\n      'Do not edit by hand — run `pnpm docs:generate` to refresh._',","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/generate-architecture-docs.mjs#L61-L97","documentation":"parseProviderChain() rejects any row whose component name or role text contains `|`, because the rendered output is a markdown table and a pipe would break or inject columns. This runs on both p.name and p.role after parsing, so the pipe can be on either side of the em dash.","triggerScenarios":"Writing shorthand like `* 7. layout | theme — split state` or a role like `proxies socket | MCP traffic`; even a single `|` anywhere in either field throws with the row number.","commonSituations":"Describing dual responsibility with a pipe ('A | B'); pasting CLI usage text (e.g. `--flags | jq`) into a role description.","solutions":["Replace the `|` in the flagged row with `/`, `or`, or a comma","If the pipe is essential (command syntax), move that detail to prose outside the marker block","Re-run the generator; the table renders with intact columns"],"exampleFix":"// before:\n * 9. socketService — keeps socketService | MCP transport aligned\n\n// after:\n * 9. socketService — keeps socketService and MCP transport aligned","handlingStrategy":"validation","validationCode":"for (const m of rows.map(l => ROW_RE.exec(l))) {\n  if (m[2].includes('|') || m[3].includes('|')) {\n    console.error(`Row ${m[1]} contains a pipe — replace '|' with '/' or 'or'`);\n    process.exit(1);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use `|` shorthand in marker rows — write 'and' or '/' (the rendered artifact is a markdown table)","Keep command-syntax snippets out of the role column; put them in prose outside the markers"],"tags":["docs","codegen","markdown","validation"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}