denoland/deno · error
nul byte found in provided data
Error message
nul byte found in provided data
What it means
On Windows, Deno builds the child-process environment block by encoding every variable name and value as NUL-terminated UTF-16 in make_envp(). Before that, ensure_no_nuls() scans each key and value and rejects any that already contain a U+0000, because an embedded NUL would terminate the entry early and silently corrupt the rest of the block. The failure surfaces from Deno.Command spawn as an InvalidInput error ('nul byte found in provided data').
Source
Thrown at runtime/subprocess_windows/src/env.rs:227
// they are compared using a caseless string mapping.
impl From<OsString> for EnvKey {
fn from(k: OsString) -> Self {
EnvKey {
utf16: k.encode_wide().collect(),
os_string: k,
}
}
}
impl From<&OsStr> for EnvKey {
fn from(k: &OsStr) -> Self {
Self::from(k.to_os_string())
}
}
pub fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> io::Result<T> {
if s.as_ref().encode_wide().any(|b| b == 0) {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"nul byte found in provided data",
))
} else {
Ok(s)
}
}
pub fn make_envp(
maybe_env: Option<BTreeMap<EnvKey, OsString>>,
) -> io::Result<(*mut c_void, Vec<u16>)> {
// On Windows we pass an "environment block" which is not a char**, but
// rather a concatenation of null-terminated k=v\0 sequences, with a final
// \0 to terminate.
if let Some(env) = maybe_env {
let mut blk = Vec::new();
// If there are no environment variables to set then signal this byView on GitHub (pinned to 9ad36f7a2c)
Solutions
- Strip or reject U+0000 in every env key and value before passing env to Deno.Command
- Pass binary data via stdin, a temp file, or argv instead of environment variables
- Add a spawn smoke test that uses the exact env map your app builds so NULs are caught before deployment
Example fix
// before
const cmd = new Deno.Command("cmd.exe", {
env: { TOKEN: "abc\u0000def" }, // embedded NUL -> spawn fails
});
const child = cmd.spawn();
// after
const clean = (s: string) => s.replaceAll("\u0000", "");
const env = Object.fromEntries(
Object.entries(rawEnv).map(([k, v]) => [clean(k), clean(String(v))]),
);
const cmd = new Deno.Command("cmd.exe", { env });
const child = cmd.spawn(); Defensive patterns
Strategy: validation
Validate before calling
const hasNul = (s: string) => s.includes("\u0000");
function assertCleanEnv(env: Record<string, string>) {
for (const [k, v] of Object.entries(env)) {
if (hasNul(k) || hasNul(v)) {
throw new Error(`NUL byte in environment entry: ${JSON.stringify(k)}`);
}
}
}
// assertCleanEnv(env) before new Deno.Command(prog, { env }) Try / catch
try {
const child = cmd.spawn();
} catch (err) {
if (err instanceof TypeError && err.message.includes("nul byte")) {
// sanitize env (strip U+0000) and retry spawn
} else throw err;
} Prevention
- Never pass binary blobs through env vars; use stdin or temp files
- Sanitize strings read from files, registries, or protocols before injecting them into env
- On Windows CI, run a spawn smoke test with the exact env map production builds
When it happens
Trigger: Calling new Deno.Command(prog, { env: {...} }).spawn() / .output() on Windows when any env key or value contains a NUL character, e.g. env: { TOKEN: "a\u0000b" }. make_envp() runs ensure_no_nuls() over every entry of the env map supplied to the spawn options.
Common situations: Env values copied verbatim from binary files, protobuf/length-prefixed buffers, or Windows registry strings that carry embedded NUL terminators; passing serialized data through environment variables; strings assembled with String.fromCharCode(0).
Related errors
- env contains NUL
- File not found
- Windows file names may not contain `"` or end with `\`
- nul byte found in provided data
- program path contains NUL
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/3fd435259066eeb7.
Report an issue: GitHub.