{"record":{"id":"efe245ea48256b3b","repo":"denoland/deno","slug":"invalid-doc-test-hashbang-reason","errorCode":null,"errorMessage":"invalid doc test hashbang: {} ({reason})","messagePattern":"invalid doc test hashbang: (.+?) \\((.+?)\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/util/extract.rs","lineNumber":557,"sourceCode":"  Invalid(String),\n}\n\n/// Parses a shebang line like `#!/usr/bin/env -S deno run --allow-read`.\n///\n/// The flags are parsed using deno's own CLI argument parser and the resulting\n/// permissions are forwarded to `Deno.test`.\n///\n/// Known limitations:\n/// - The `deno` executable is matched by file name, so custom-named binaries\n///   (e.g. `deno-canary`) are not recognized and yield an invalid shebang.\n/// - A scoped `--deny-*=<path>` cannot be represented in the `Deno.test`\n///   permissions object yet and yields an invalid shebang to force failure\n/// - A `--ignore-*` cannnot be represented in the `Deno.test` permissions\n///   object either yet, so they are currently ignored\nfn parse_shebang(shebang: &str) -> Shebang {\n  let invalid = |reason: &str| {\n    Shebang::Invalid(format!(\n      \"invalid doc test hashbang: {} ({reason})\",\n      shebang.trim()\n    ))\n  };\n  let Some(line) = shebang.trim_start().strip_prefix(\"#!\") else {\n    return invalid(\"invalid hashbang\");\n  };\n  let Some(tokens) = shlex::split(line) else {\n    return invalid(\"tokenization failed, possibly due to unterminated quotes\");\n  };\n  // Find the `deno` executable in the shebang (e.g. `deno`, `/usr/bin/deno`).\n  let Some(deno_index) = tokens.iter().position(|token| {\n    std::path::Path::new(token)\n      .file_stem()\n      .and_then(|stem| stem.to_str())\n      == Some(\"deno\")\n  }) else {\n    return invalid(\"binary basename needs to be 'deno'\");\n  };","sourceCodeStart":539,"sourceCodeEnd":575,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/util/extract.rs#L539-L575","documentation":"`deno test` extracts fenced code blocks from JSDoc @example tags and markdown docs and runs them as doc tests. The block's shebang (e.g. `#!/usr/bin/env -S deno run --allow-read`) is parsed by parse_shebang in cli/util/extract.rs to derive the Deno.test permissions for the generated test; when the shebang cannot be parsed or represented, the test is marked invalid (forcing failure) with this message plus a parenthesized reason.","triggerScenarios":"Shebang not starting with '#!' after trimming; shell tokenization failure (unterminated quotes); no token naming the `deno` executable (e.g. a custom binary name like `deno-canary`); scoped `--deny-*=<path>` permissions that the permissions object cannot express yet.","commonSituations":"Writing doc examples with unusual shebangs; CI environments using a renamed deno binary; documenting scoped deny flags or ignore flags in example shebangs.","solutions":["Use the canonical form: `#!/usr/bin/env -S deno run` plus simple unscoped flags","Remove scoped `--deny-*=<path>` flags from doc example shebangs - they are not representable and force invalid","Quote shebang arguments properly; avoid unterminated quotes","Do not rely on the binary being named exactly `deno` - renamed binaries are not recognized"],"exampleFix":"# before\n#!/usr/bin/env -S deno run --deny-read=/etc\n\n# after\n#!/usr/bin/env -S deno run --allow-read","handlingStrategy":"validation","validationCode":"function checkShebang(line: string): string | null {\n  const s = line.trim();\n  if (!s.startsWith(\"#!/usr/bin/env -S deno\")) return \"missing canonical deno shebang\";\n  if (/['\\\"]/.test(s) && !/(['\\\"]).*?\\1/.test(s)) return \"unterminated quote\";\n  return null; // ok\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the canonical `#!/usr/bin/env -S deno run` prefix in doc examples","Avoid scoped `--deny-*=<path>` flags in example shebangs","Keep the binary name `deno` in doc-test shebangs; renamed binaries are not recognized","Run `deno test --doc` locally so shebang problems surface before CI"],"tags":["doc-tests","shebang","permissions","deno-test"],"backgroundTag":"invalid-shebang","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}