{"record":{"id":"55a4f9ae8b553c3e","repo":"paperclipai/paperclip","slug":"filename-no-captured-states","errorCode":null,"errorMessage":"${fileName}: no captured states","messagePattern":"(.+?): no captured states","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/ingest-app-definitions.mjs","lineNumber":1480,"sourceCode":"\n];\nfor (const slug of reviewedGoogleSlugs) {\n  const existingIndex = apps.findIndex((app) => app.slug === slug);\n  if (existingIndex >= 0) apps.splice(existingIndex, 1);\n  apps.push(\n    JSON.parse(fs.readFileSync(path.join(out, `${slug}.json`), \"utf8\")),\n  );\n}\nconst parseTableRow = (line) =>\n  line\n    .slice(1, -1)\n    .split(\"|\")\n    .map((cell) => cell.trim());\nconst parseCapture = (fileName) => {\n  const markdown = fs.readFileSync(path.join(corpus, fileName), \"utf8\");\n  const stateMatches = [...markdown.matchAll(/^## State: (.+)$/gm)];\n  if (stateMatches.length === 0)\n    throw new Error(`${fileName}: no captured states`);\n  return stateMatches.map((match, index) => {\n    const body = markdown.slice(\n      match.index + match[0].length,\n      stateMatches[index + 1]?.index ?? markdown.length,\n    );\n    const inputsBlock =\n      body.match(/### Inputs\\n([\\s\\S]*?)(?=\\n### |$)/)?.[1] ?? \"\";\n    const inputRows = inputsBlock\n      .split(\"\\n\")\n      .filter((line) => line.startsWith(\"|\"))\n      .slice(2)\n      .map(parseTableRow);\n    const fields = inputRows.map(\n      ([label, tagType, required, placeholder, prefilledValue, checked]) => ({\n        label,\n        tagType,\n        required: required.toLowerCase() === \"yes\",\n        placeholder: placeholder || null,","sourceCodeStart":1462,"sourceCodeEnd":1498,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/scripts/ingest-app-definitions.mjs#L1462-L1498","documentation":"parseCapture() reads a corpus capture markdown file and extracts connection-flow states via /^## State: (.+)$/gm headings. A capture file with zero such headings is unusable — it contains no replayable states — so ingestion rejects it outright to prevent emitting an empty interaction definition.","triggerScenarios":"parseCapture(fileName) is called for each *.md file (except INDEX.md) in the captures corpus directory (PAPERCLIP_CONTENT_TEMPLATES or ../../paperclip-content/research/connections/vercel/templates) and the file content has no lines matching '^## State: '.","commonSituations":"A contributor added a new capture .md file that only has prose or a different heading convention (e.g. '### state:' or '# State:'); a file was copied but body content was never filled in; an editor or linter stripped/renamed the '## State:' headings; wrong corpus directory env var points at unrelated markdown files that happen to end in .md.","solutions":["Edit the capture .md file so it contains at least one '## State: <Name>' heading, with the state's content below it.","Compare with an existing valid capture file and match its heading format exactly ('## State: ' with two hashes and a colon-space).","Check PAPERCLIP_CONTENT_TEMPLATES points at the intended templates directory; a wrong corpus dir pulls in non-capture markdown.","If the file is a placeholder or index-like doc, delete it or rename it so it does not match the *.md corpus glob (or list it as INDEX.md-style excluded name)."],"exampleFix":"// before (capture.md)\n# Slack connection\nSome prose only.\n// after\n# Slack connection\n## State: Initial\nDescribe the initial captured state here.","handlingStrategy":"validation","validationCode":"const md = fs.readFileSync(file, 'utf8');\nif (!/^## State: /m.test(md)) throw new Error(`${file}: missing '## State:' headings`);","typeGuard":null,"tryCatchPattern":"try { const states = parseCapture(fileName); } catch (e) { if (e.message.endsWith('no captured states')) { console.error(`Capture ${fileName} has no '## State:' headings; fix the file format.`); process.exitCode = 1; } else throw e; }","preventionTips":["Copy the template heading format ('## State: Name') from an existing capture when authoring new ones.","Add a lint rule that flags .md files in the corpus lacking '## State:' headings.","Never rename state headings without updating the parser regex."],"tags":["parsing","markdown","capture","ingest"],"backgroundTag":"empty-result-set","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}