denoland/deno · error · TypeError
${name} is not a function
Error message
${name} is not a function What it means
Implements ECMA-262 GetMethod for WebIDL: reads property P on V; null/undefined means 'absent', but any other non-callable value throws TypeError. Symbol keys are formatted with Symbol.prototype.toString so the message reads engine-style, e.g. 'Symbol(aaa) is not a function'. Used by iterator/async-iterator protocol lookups (isAsyncSequence) and converters.
Source
Thrown at ext/webidl/00_webidl.js:1010
`${context}, index ${array.length}`,
opts,
);
ArrayPrototypePush(array, val);
}
return array;
};
}
// https://tc39.es/ecma262/#sec-getmethod
function getMethod(V, P) {
const func = V[P];
if (func === undefined || func === null) {
return undefined;
}
if (typeof func !== "function") {
// Match engine-style key formatting: Symbol(aaa), not the bare description.
const name = typeof P === "symbol" ? SymbolPrototypeToString(P) : P;
throw new TypeError(`${name} is not a function`);
}
return func;
}
// Whether V is convertible to an IDL async_sequence (has a usable
// @@asyncIterator or @@iterator method). Uses GetMethod, so non-callable
// methods throw TypeError (same as conversion / union matching).
function isAsyncSequence(obj) {
if (type(obj) !== "Object") {
return false;
}
if (getMethod(obj, SymbolAsyncIterator) !== undefined) {
return true;
}
return getMethod(obj, SymbolIterator) !== undefined;
}
// https://tc39.es/ecma262/#sec-createasyncfromsynciteratorView on GitHub (pinned to f7822238ca)
Solutions
- Make the property a real method: [Symbol.asyncIterator]() { return this; }
- Or set the property to null/undefined (or delete it) so it counts as absent instead of invalid
- Never store iterator objects under @@iterator/@@asyncIterator keys - store the iterable and let the method be invoked
Example fix
// before
const body = { [Symbol.asyncIterator]: source[Symbol.asyncIterator]() }; // object, not a function
// after
const body = { [Symbol.asyncIterator]() { return source[Symbol.asyncIterator](); } }; Defensive patterns
Strategy: type-guard
Validate before calling
function checkProtocolMethods(v: object, key: symbol | string) {
const m = (v as any)[key];
if (m != null && typeof m !== 'function') {
throw new TypeError(`${String(key)} must be a function or null`);
}
}
checkProtocolMethods(body, Symbol.asyncIterator); Type guard
const isAsyncIterable = (v: unknown): v is AsyncIterable<unknown> => v != null && typeof (v as Record<PropertyKey, unknown>)[Symbol.asyncIterator] === 'function';
Prevention
- Use method shorthand for symbol keys: [Symbol.asyncIterator]() { ... }
- Type values as AsyncIterable<T> so TypeScript flags non-callable assignments
- Never store an already-called iterator under a protocol key - store the iterable
When it happens
Trigger: Passing an object used as an iterable/async-iterable (e.g. a fetch body) where @@asyncIterator or @@iterator exists but is not callable, e.g. { [Symbol.asyncIterator]: 42 } or { [Symbol.iterator]: someArray }.
Common situations: Storing an already-called iterator under the symbol key instead of a method ({ [Symbol.asyncIterator]: stream[Symbol.asyncIterator]() }), spreading config objects that overwrite protocol methods with data values, polyfills assigning non-callable symbol properties.
Related errors
- Cannot convert a Symbol value to a string
- ${openContext} failed to iterate next value because the next
- ${openContext} failed to close iterator because the return()
- Cannot convert a BigInt value to a number
- The iterator.next() method must return an object
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/7ea02ab406c12256.
Report an issue: GitHub.