denoland/deno · error · TypeError
ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE
Error message
The "channel" argument must be one of type string or symbol. Received ${actual} What it means
diagnostics_channel.channel(name) (and everything built on it: subscribe(), unsubscribe(), TracingChannel's string form) requires the channel identifier to be a string or a symbol. The WeakRefMap cache is consulted first, but a non-string/non-symbol name is never cached, so it always falls through to this ERR_INVALID_ARG_TYPE.
Source
Thrown at ext/node/polyfills/diagnostics_channel.js:254
get hasSubscribers() {
return false;
}
publish() {}
runStores(_data, fn, thisArg, ...args) {
return ReflectApply(fn, thisArg, args);
}
}
const channels = new WeakRefMap();
function channel(name) {
const ch = channels.get(name);
if (ch) return ch;
if (typeof name !== "string" && typeof name !== "symbol") {
throw new ERR_INVALID_ARG_TYPE("channel", ["string", "symbol"], name);
}
return new Channel(name);
}
function subscribe(name, subscription) {
return channel(name).subscribe(subscription);
}
function unsubscribe(name, subscription) {
return channel(name).unsubscribe(subscription);
}
function hasSubscribers(name) {
const ch = channels.get(name);
if (!ch) return false;
return ch.hasSubscribers;View on GitHub (pinned to 89f33cbef2)
Solutions
- Coerce to string explicitly: dc.channel(String(name))
- Use Symbol.for('namespace:channel') for collision-free symbolic names
- If you already hold a Channel instance, use it directly instead of calling channel() again
Example fix
// before const name = 42; // from a numeric enum const ch = dc.channel(name); // throws // after const ch = dc.channel(String(name));
Defensive patterns
Strategy: type-guard
Validate before calling
const name2 = typeof name === 'symbol' ? name : String(name); const ch = dc.channel(name2);
Type guard
const isChannelName = (v) => typeof v === 'string' || typeof v === 'symbol';
Prevention
- Stringify numeric enum values at the channel boundary
- Create channels once in a registry module and pass Channel objects around, not names
- Use Symbol.for for namespaced channels when string collisions are a risk
When it happens
Trigger: dc.channel(42); dc.subscribe(['http'], fn); dc.unsubscribe(null, fn); new TracingChannel({ toString: () => 'x' }) paths that stringify late — anything where the name is not literally string or symbol.
Common situations: Names built from enums stored as numbers, values read from structured config, iterating object keys with a numeric index, or passing a channel object where the name is expected.
Related errors
- resolve hook must return { shortCircuit: true } or call next
- load hook must return { shortCircuit: true } or call nextLoa
- A file exists at the destination: ${destStr}
- ERR_MISSING_ARGS
- No callback function supplied
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/11f8d5f5579abf82.
Report an issue: GitHub.