colinhacks/zod · error · Error
implement() must be called with a function
Error message
implement() must be called with a function
What it means
Thrown by `inst.implement(func)` on a `z.function()` schema when the argument is not a function. `.implement()` wraps a callback so its arguments and return value are validated against the function schema's input/output types; it requires an actual function to wrap.
Source
Thrown at packages/zod/src/v4/core/schemas.ts:4432
output<NewReturns extends $ZodType>(output: NewReturns): $ZodFunction<Args, NewReturns>;
}
export interface $ZodFunctionParams<I extends $ZodFunctionIn, O extends $ZodType> {
input?: I;
output?: O;
}
export const $ZodFunction: core.$constructor<$ZodFunction> = /*@__PURE__*/ core.$constructor(
"$ZodFunction",
(inst, def) => {
$ZodType.init(inst, def);
inst._def = def;
inst._zod.def = def;
inst.implement = (func) => {
if (typeof func !== "function") {
throw new Error("implement() must be called with a function");
}
return function (this: any, ...args: never[]) {
const parsedArgs = inst._def.input ? parse(inst._def.input, args) : args;
const result = Reflect.apply(func, this, parsedArgs as never[]);
if (inst._def.output) {
return parse(inst._def.output, result);
}
return result as any;
};
};
inst.implementAsync = (func) => {
if (typeof func !== "function") {
throw new Error("implementAsync() must be called with a function");
}
return async function (this: any, ...args: never[]) {
const parsedArgs = inst._def.input ? await parseAsync(inst._def.input, args) : args;
const result = await Reflect.apply(func, this, parsedArgs as never[]);View on GitHub (pinned to 912f0f51b0)
Solutions
- Pass an actual function to `.implement()`, e.g. `schema.implement((arg) => ...)`.
- If the handler is optional/dynamic, guard with `if (typeof handler === 'function') schema.implement(handler)`.
- Check imports/variable bindings — the value is likely undefined due to a missing or misnamed import.
Example fix
// before
const fn = z.function(z.string(), z.boolean()).implement({ run: (s) => !!s });
// after
const fn = z.function(z.string(), z.boolean()).implement((s) => !!s); Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof handler !== 'function') throw new Error('handler must be a function');
const wrapped = fnSchema.implement(handler); Type guard
function isFunction(v): boolean { return typeof v === 'function'; } Try / catch
try {
const wrapped = fnSchema.implement(handler);
} catch (e) {
if (e instanceof Error && e.message === 'implement() must be called with a function') {
// ensure handler is defined and is a function before retrying
}
throw e;
} Prevention
- Type the handler parameter explicitly as a function so the compiler catches non-functions.
- Guard dynamic handlers with typeof checks before calling .implement().
- Verify imports/initialization order to avoid undefined handlers.
When it happens
Trigger: Calling `.implement(undefined)`, `.implement(null)`, `.implement('some string')`, or passing an object/array to a function schema's `.implement()`. Often a typo, an unset variable, or a wrong import.
Common situations: Calling `.implement()` before assigning the handler; passing a config object instead of a function; dynamic dispatch where the handler variable is conditionally defined.
Related errors
- implementAsync() must be called with a function
- Invalid UUID version: "${def.version}"
- Invalid discriminated union option at index "${def.options.i
- Invalid discriminated union option at index "${def.options.i
- Duplicate discriminator value "${String(v)}"
AI-assisted analysis of colinhacks/zod@912f0f51b0 (2026-08-03).
Data as JSON: /data/errors/fd19a44cf3783f59.json.
Report an issue: GitHub.