denoland/deno · error · TypeError
resolve hook must return { shortCircuit: true } or call next
Error message
resolve hook must return { shortCircuit: true } or call nextResolve What it means
Under Node's module.registerHooks() (synchronous module customization hooks, polyfilled by Deno's CJS loader in ext/node/polyfills/01_require.js), every resolve hook must either delegate by calling nextResolve() or take responsibility by returning an object containing shortCircuit: true. If the hook returns undefined (or anything lacking shortCircuit) and never chained, the runner throws this TypeError because the resolution chain cannot continue.
Source
Thrown at ext/node/polyfills/01_require.js:757
try {
const resolved = new URL(spec, currentContext.parentURL).href;
return { url: resolved, shortCircuit: true };
} catch {
return { url: null, shortCircuit: true };
}
} finally {
insideResolveHook = false;
}
}
const hook = resolveHooks[index++];
let nextCalled = false;
const wrappedNext = (s, c) => {
nextCalled = true;
return nextResolve(s, c);
};
const result = hook(spec, currentContext, wrappedNext);
if (!nextCalled && !result?.shortCircuit) {
throw new TypeError(
"resolve hook must return { shortCircuit: true } or call nextResolve",
);
}
return result;
}
return nextResolve(specifier, context);
}
function esmResolveHookCallback(specifier, referrer, importAttributes) {
const attrs = { __proto__: null };
if (importAttributes !== null && typeof importAttributes === "object") {
for (const key in importAttributes) {
attrs[key] = importAttributes[key];
}
}
const context = {
parentURL: referrer || undefined,View on GitHub (pinned to 89f33cbef2)
Solutions
- Make every code path either return { url, shortCircuit: true, format } or return nextResolve(spec, context)
- Use the ternary shape: return cond ? { url, shortCircuit: true } : nextResolve(spec, context)
- Add an explicit `return nextResolve(spec, context);` as the last statement of the hook body
Example fix
// before
module.registerHooks({
resolve(spec, context, nextResolve) {
if (spec.startsWith("virtual:")) {
return { url: `virtual:${spec}`, shortCircuit: true, format: "module" };
}
// falls through: no return, no nextResolve -> TypeError
},
});
// after
module.registerHooks({
resolve(spec, context, nextResolve) {
if (spec.startsWith("virtual:")) {
return { url: `virtual:${spec}`, shortCircuit: true, format: "module" };
}
return nextResolve(spec, context);
},
}); Defensive patterns
Strategy: validation
Validate before calling
// Write hooks as total functions: every path either short-circuits or chains.
const resolveHook = (spec: string, context: object, nextResolve: Function) =>
spec.startsWith("virtual:")
? { url: `virtual:${spec}`, shortCircuit: true, format: "module" }
: nextResolve(spec, context);
module.registerHooks({ resolve: resolveHook }); Type guard
function isResolveResult(v: unknown): v is { url: string; shortCircuit?: boolean; format?: string } {
return v != null && typeof v === "object" && "url" in v;
} Prevention
- End every hook body with an explicit `return nextResolve(spec, context);`
- Prefer ternary/early-return shapes that make missing-return paths impossible
- Cover hooks with unit tests that drive both the custom branch and the fall-through branch
When it happens
Trigger: module.registerHooks({ resolve(spec, ctx, nextResolve) { if (spec.startsWith('virtual:')) return { url: spec, shortCircuit: true }; } }) - the non-virtual path neither returns a shortCircuit result nor calls nextResolve; forgetting `return` in an arrow body; a conditional that only returns on some branches.
Common situations: Porting registerHooks or module.register loader code from Node; writing hooks where the default path silently falls off the end; refactoring hooks and dropping the final return nextResolve(...) line.
Related errors
- load hook must return { shortCircuit: true } or call nextLoa
- Module already loaded
- 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/7a2876aedafb57d4.
Report an issue: GitHub.