denoland/deno · error · Error
invalid doc test hashbang: #!/usr/bin/env -S deno run --allo
Error message
invalid doc test hashbang: #!/usr/bin/env -S deno run --allow-read --deny-read=/etc (scoped --deny-* flags aren't supported yet, either remove them or ignore the test)
What it means
Doc-test shebangs are parsed with Deno's own CLI flag parser and forwarded as the generated test's permission set. has_scoped_deny() (cli/util/extract.rs:588) reports true when any --deny-* flag carries a non-empty value list (deny_env/ffi/import/net/read/run/sys/write). Scoped denies like --deny-read=/etc cannot be expressed in the Deno.test permissions object, so the generated test throws this Error rather than running with broader permissions than the shebang declares.
Source
Thrown at cli/util/extract.rs:2084
// A scoped `--deny-*` can't be modelled, so the test is made to fail
// rather than run with broader permissions than the shebang declares.
Test {
input: Input {
source: r#"
/**
* ```ts
* #!/usr/bin/env -S deno run --allow-read --deny-read=/etc
* foo();
* ```
*/
export function foo() {}
"#,
specifier: "file:///main.ts",
},
expected: vec![Expected {
source: r#"import { foo } from "file:///main.ts";
Deno.test("file:///main.ts#3-7.ts", async ()=>{
throw new Error("invalid doc test hashbang: #!/usr/bin/env -S deno run --allow-read --deny-read=/etc (scoped --deny-* flags aren't supported yet, either remove them or ignore the test)");
foo();
});
"#,
specifier: "file:///main.ts#3-7.ts",
media_type: MediaType::TypeScript,
}],
},
// A bare `--deny-*` becomes `false`; only the flags present in the
// shebang end up in the permissions object.
Test {
input: Input {
source: r#"
/**
* ```ts
* #!/usr/bin/env -S deno run --allow-read --deny-env
* foo();
* ```
*/View on GitHub (pinned to 89f33cbef2)
Solutions
- Remove the scoped --deny-*=... flag from the example's shebang
- Use a whole-flag deny instead, e.g. bare --deny-read (no value), which maps to permissions: { read: false } and is supported
- Mark the fence as ignored with ```ts ignore
Example fix
// before /** * ```ts * #!/usr/bin/env -S deno run --allow-read --deny-read=/etc * foo(); * ``` */ // after /** * ```ts * #!/usr/bin/env -S deno run --allow-read --deny-read * foo(); * ``` */
Defensive patterns
Strategy: validation
Validate before calling
// CI check: no scoped --deny-*=<value> flags in doc-test shebangs grep -rn --include='*.ts' -- '--deny-[a-z]*=' src/ | grep '#!' || true
Prevention
- Use bare --deny-<perm> (no '=value') in documented shebangs
- Remember scoped denies cannot be modelled in Deno.test permissions yet - do not copy hardened script shebangs verbatim into docs
- Mark fences that need scoped denies with ```ts ignore
When it happens
Trigger: A ```ts doc-test fence starting with #!/usr/bin/env -S deno run --allow-read --deny-read=/etc (any --deny-<perm>=<value> form) executed under deno test --doc.
Common situations: Documenting hardened scripts that exclude sensitive paths via scoped deny flags; copying a real-world shebang from a script into its doc comment; hardening examples added during a security pass that then break doc tests.
Related errors
- invalid doc test hashbang: #!/bin/sh (binary basename needs
- Bench failed because the "only" option was used
- Bench failed
- The bench name can't be empty
- Expected the second argument to assertSnapshot() to be an op
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/6d998f853b0b980b.
Report an issue: GitHub.