denoland/deno · error · TypeError
Cannot construct UnsafeCallback: cannot be nonblocking
Error message
Cannot construct UnsafeCallback: cannot be nonblocking
What it means
Deno.UnsafeCallback(definition, callback) creates a native trampoline that must invoke JS on a live runtime thread. The nonblocking option exists for dlopen function symbols (run the foreign call on the thread pool); it has no meaning for callbacks and is rejected at construction time.
Solutions
- Remove nonblocking from the callback definition object
- Keep separate definition objects for dlopen functions and UnsafeCallbacks
- If async behavior is needed, mark the foreign function nonblocking, not the callback
Example fix
// before
const cb = new Deno.UnsafeCallback(
{ parameters: ["i32"], result: "void", nonblocking: true },
(n) => {},
);
// after
const cb = new Deno.UnsafeCallback(
{ parameters: ["i32"], result: "void" },
(n) => {},
); Defensive patterns
Strategy: validation
Validate before calling
function toCallbackDefinition(def) {
const { nonblocking: _, ...rest } = def; // strip FFI-function-only options
return rest;
}
const cb = new Deno.UnsafeCallback(
toCallbackDefinition(def),
handler,
); Prevention
- Keep separate definition objects for dlopen functions and UnsafeCallbacks
- never reuse a nonblocking function definition for a callback
- Mark the foreign function nonblocking when you need async, not the callback
When it happens
Trigger: new Deno.UnsafeCallback({ parameters: [...], result: 'void', nonblocking: true }, cb); reusing one shared definition object (with nonblocking: true) for both dlopen symbols and UnsafeCallback creation.
Common situations: A single FFI config object shared across function and callback declarations; copy-pasting a nonblocking function definition into a callback definition.
Related errors
- Unable to deserialize result parameter.
- Cannot access pointer: expected 'ArrayBuffer'…
- Cannot get pointer size: found recursive struct
- Cannot get pointer size, unsupported type
- 'create' or 'createNew' options require 'write' or 'append'…
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/e043942e10636067.
Report an issue: GitHub.
Appendix: source
Thrown at ext/ffi/00_ffi.js:405
case "isize":
return [8, 8];
default:
throw new TypeError(`Cannot get pointer size, unsupported type: ${type}`);
}
}
class UnsafeCallback {
#refcount;
// Internal promise only meant to keep Deno from exiting
#refpromise;
#rid;
definition;
callback;
pointer;
constructor(definition, callback) {
if (definition.nonblocking) {
throw new TypeError(
"Cannot construct UnsafeCallback: cannot be nonblocking",
);
}
const { 0: rid, 1: pointer } = op_ffi_unsafe_callback_create(
definition,
callback,
);
this.#refcount = 0;
this.#rid = rid;
this.pointer = pointer;
this.definition = definition;
this.callback = callback;
}
static threadSafe(definition, callback) {
const unsafeCallback = new UnsafeCallback(definition, callback);
unsafeCallback.ref();
return unsafeCallback;View on GitHub (pinned to 9ad36f7a2c)