{"record":{"id":"5e1e8d3f8b85e24a","repo":"oven-sh/bun","slug":"could-not-find-quick-links-in-readme","errorCode":null,"errorMessage":"Could not find ## Quick links in README","messagePattern":"Could not find ## Quick links in README","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/nav2readme.ts","lineNumber":82,"sourceCode":"\n  let prevDirname = \"\";\n  for (const { name, file } of files) {\n    const dirname = path.basename(path.dirname(file));\n    if (dirname !== prevDirname) {\n      md += `\\n- ${normalizeSectionName(dirname)} ` + \"\\n\";\n      prevDirname = dirname;\n    }\n    md +=\n      `  - [${name}](https://bun.com/guides/${path.dirname(file)}/${path.basename(file, path.extname(file))})` + \"\\n\";\n  }\n\n  return md;\n}\n\nconst text = await Bun.file(Bun.fileURLToPath(import.meta.resolve(\"../README.md\"))).text();\nconst startI = text.indexOf(\"## Quick links\\n\");\nif (startI === -1) {\n  throw new Error(\"Could not find ## Quick links in README\");\n}\nconst start = startI + \"## Quick links\\n\".length;\n\nconst contributing = text.indexOf(\"## Contributing\\n\", start);\n\nif (contributing === -1) {\n  throw new Error(\"Could not find ## Contributing in README\");\n}\n\nconst guides = await getGuides();\n\nconst combined =\n  [text.slice(0, start), getQuickLinks(), guides, text.slice(contributing)].map(text => text.trim()).join(\"\\n\\n\") +\n  \"\\n\";\n\nawait Bun.write(Bun.fileURLToPath(import.meta.resolve(\"../README.md\")), combined);\n\nfunction normalizeSectionName(name: string) {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/scripts/nav2readme.ts#L64-L100","documentation":"scripts/nav2readme.ts regenerates the guides listing inside the repo README.md by locating the literal sentinel heading `## Quick links\\n` with indexOf. A -1 result means the heading is not present byte-for-byte, so the script cannot know where to inject the generated list.","triggerScenarios":"The heading was renamed or re-capitalized (`## Quick Links`), the README was restructured, or line endings changed to CRLF so the `\\n` in the search string never matches. Any edit that removes the exact `## Quick links` line triggers it.","commonSituations":"Docs rewrites that rename sections; a git autocrlf checkout on Windows converting the README to CRLF; running the script against a different repository's README.","solutions":["Restore the exact heading `## Quick links` on its own line in README.md","Normalize line endings to LF (`git config core.autocrlf false` and re-checkout, or dos2unix README.md)","Keep the section order intact: Quick links must appear before Contributing so both sentinels resolve"],"exampleFix":"# before\n## Quick Links\\n\\n<!-- guides -->\\n\\n## Contributing\\n\n# after\n## Quick links\\n\\n<!-- regenerated -->\\n\\n## Contributing\\n","handlingStrategy":"validation","validationCode":"const readme = await Bun.file(\"README.md\").text();\nif (!readme.includes(\"## Quick links\\n\") || readme.includes(\"\\r\\n\")) {\n  throw new Error(\"README.md lost the `## Quick links` sentinel or has CRLF endings — fix before nav2readme\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat the two sentinel headings as load-bearing markers in docs reviews; rename them only with a matching nav2readme.ts change","Set core.autocrlf=false (or add .gitattributes `README.md text eol=lf`) on Windows checkouts","Run `bun scripts/nav2readme.ts` in CI on docs PRs so a broken sentinel fails early"],"tags":["docs","readme","automation","markdown","line-endings"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}