denoland/deno · error · anyhow::Error
Invalid serialization type
Error message
Invalid serialization type: {} What it means
When a Deno process starts with NODE_CHANNEL_FD set — how node:child_process.fork() wires the IPC channel to the child — it also reads NODE_CHANNEL_SERIALIZATION_MODE and parses it into ChildIpcSerialization, which accepts exactly "json" or "advanced" (FromStr in ext/node/ops/ipc.rs:11-23, wired from cli/lib/args.rs:56-68). Any other string aborts startup with "Invalid serialization type: {s}". fork() itself validates the option, so this almost always comes from hand-rolled spawns that set the env vars directly.
Solutions
- Use one of the two accepted lowercase values: NODE_CHANNEL_SERIALIZATION_MODE=json or =advanced.
- If the child should not have IPC at all, unset both NODE_CHANNEL_FD and NODE_CHANNEL_SERIALIZATION_MODE in the spawn env.
- Prefer node:child_process.fork() from a Node/Deno parent — it sets the env correctly and validates the option for you.
Example fix
// before
spawn('deno', ['child.ts'], {
env: { ...process.env, NODE_CHANNEL_FD: '3', NODE_CHANNEL_SERIALIZATION_MODE: 'JSON' },
});
// child dies at startup: Invalid serialization type: JSON
// after
spawn('deno', ['child.ts'], {
env: { ...process.env, NODE_CHANNEL_FD: '3', NODE_CHANNEL_SERIALIZATION_MODE: 'json' },
}); Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the env before spawning a Deno child with an IPC channel
const modes = new Set(["json", "advanced"]);
const mode = process.env.NODE_CHANNEL_SERIALIZATION_MODE;
if (process.env.NODE_CHANNEL_FD && (mode !== undefined) && !modes.has(mode)) {
throw new Error(`NODE_CHANNEL_SERIALIZATION_MODE must be json|advanced, got ${mode}`);
} Type guard
type IpcSerialization = "json" | "advanced"; const isIpcSerialization = (v: string): v is IpcSerialization => v === "json" || v === "advanced";
Prevention
- Use exactly lowercase json or advanced — the value is case-sensitive.
- Unset both NODE_CHANNEL_FD and NODE_CHANNEL_SERIALIZATION_MODE when the child should have no IPC.
- Prefer node:child_process.fork() over hand-setting these env vars; it validates the option for you.
When it happens
Trigger: Spawning deno manually with NODE_CHANNEL_FD=3 and NODE_CHANNEL_SERIALIZATION_MODE=JSON (wrong case), or values like ini/v8/serialize; forwarding an unvalidated serialization setting from a parent tool to a Deno child meant to speak process.send().
Common situations: Replacing a Node child with a Deno child in an existing fork harness; test runners that emulate fork via env; documentation examples that set the var with the wrong casing or a Node-internal name.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- ERR_IPC_ONE_PIPE
- ERR_IPC_SYNC_FORK
- ipc stream closed before message length
- ipc stream closed while reading message
- Cannot convert a Symbol value to a string
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/af91e3a0d29070b0.
Report an issue: GitHub.
Appendix: source
Thrown at ext/node/ops/ipc.rs:17
// Copyright 2018-2026 the Deno authors. MIT license.
pub use impl_::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ChildIpcSerialization {
Json,
Advanced,
}
impl std::str::FromStr for ChildIpcSerialization {
type Err = deno_core::anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"json" => Ok(ChildIpcSerialization::Json),
"advanced" => Ok(ChildIpcSerialization::Advanced),
_ => Err(deno_core::anyhow::anyhow!(
"Invalid serialization type: {}",
s
)),
}
}
}
pub struct ChildPipeFd(pub i64, pub ChildIpcSerialization);
mod impl_ {
use std::cell::RefCell;
use std::future::Future;
use std::io;
use std::rc::Rc;
use deno_core::CancelFuture;
use deno_core::OpState;
use deno_core::RcRef;View on GitHub (pinned to 9ad36f7a2c)