{"record":{"id":"9defa08fcb461895","repo":"denoland/deno","slug":"no-callback-function-supplied","errorCode":null,"errorMessage":"No callback function supplied","messagePattern":"No callback function supplied","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/_fs/_fs_fstat.ts","lineNumber":63,"sourceCode":"    isFifo: stat.isFifo,\n    isSocket: stat.isSocket,\n  };\n}\n\nfunction fstat(\n  fd,\n  optionsOrCallback,\n  maybeCallback,\n) {\n  fd = lazyFsUtils().getValidatedFd(fd);\n  const callback = typeof optionsOrCallback === \"function\"\n    ? optionsOrCallback\n    : maybeCallback;\n  const options = typeof optionsOrCallback === \"object\"\n    ? optionsOrCallback\n    : { bigint: false };\n\n  if (!callback) throw new Error(\"No callback function supplied\");\n\n  PromisePrototypeThen(\n    op_node_fs_fstat(fd),\n    (stat) =>\n      callback(\n        null,\n        lazyStatUtils().CFISBIS(nodeFsStatToFileInfo(stat), options.bigint),\n      ),\n    (err) => callback(denoErrorToNodeError(err, { syscall: \"fstat\" })),\n  );\n}\n\nfunction fstatSync(\n  fd,\n  options,\n) {\n  fd = lazyFsUtils().getValidatedFd(fd);\n  try {","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/_fs/_fs_fstat.ts#L45-L81","documentation":"The Node-compat fs.fstat(fd, [options], callback) polyfill requires a callback function. The wrapper accepts either (fd, callback) or (fd, options, callback); if neither the second nor third argument is a function (i.e. optionsOrCallback/maybeCallback are both non-functions, typically undefined), it throws this synchronous Error before any I/O happens. This mirrors Node's rule that every async fs API must be given a callback; the synchronous variant is fs.fstatSync(fd[, options]).","triggerScenarios":"Calling fs.fstat(fd) with no further arguments; calling fs.fstat(fd, { bigint: true }) and forgetting the callback; passing the callback as the second argument while an options object occupies the callback slot, or spreading arguments in the wrong order.","commonSituations":"Porting fs.fstatSync code to the async API and forgetting the callback; refactoring a wrapper that sometimes passes options and sometimes a callback; copy-pasting a stat() call and renaming it to fstat() without updating the signature.","solutions":["Pass a callback as the final argument: fs.fstat(fd, (err, stats) => {...}) or fs.fstat(fd, { bigint: true }, cb)","If you want the result synchronously, use fs.fstatSync(fd) instead of fs.fstat(fd)","Double-check argument order when an options object is present: (fd, options, callback), never (fd, callback, options)"],"exampleFix":"// before\nfs.fstat(fd); // throws: No callback function supplied\n\n// after (async with options)\nfs.fstat(fd, { bigint: true }, (err, stats) => {\n  if (err) throw err;\n  console.log(stats.size);\n});\n\n// or sync\nconst stats = fs.fstatSync(fd);","handlingStrategy":"validation","validationCode":"if (typeof maybeCb !== 'function' && typeof optsOrCb !== 'function') { throw new TypeError('fs.fstat requires a callback; use fstatSync for sync'); }","typeGuard":"const isCallback = (v) => typeof v === 'function';","tryCatchPattern":"try { fs.fstat(fd, opts, cb); } catch (e) { /* thrown synchronously before I/O: fix the call site, don't retry */ throw e; }","preventionTips":["Prefer the fs.promises.* or *Sync variants so the callback problem disappears","In wrappers, normalize overloads once: const cb = typeof a === 'function' ? a : b; if (!cb) throw ...","Type your wrapper signatures as (fd: number, cb: (err, stats) => void) so TS flags missing callbacks at compile time"],"tags":["node-compat","fs","fstat","callback","argument-validation","deno"],"backgroundTag":"missing-callback-argument","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}