{"record":{"id":"ee547bf958448ca8","repo":"denoland/deno","slug":"no-callback-function-supplied-ee547b","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_readdir.ts","lineNumber":170,"sourceCode":"export function readdir(\n  path: string | Buffer | URL,\n  optionsOrCallback:\n    | readDirOptions\n    | string\n    | readDirCallback\n    | readDirCallbackDirent,\n  maybeCallback?: readDirCallback | readDirCallbackDirent,\n) {\n  const callback =\n    (typeof optionsOrCallback === \"function\"\n      ? optionsOrCallback\n      : maybeCallback) as readDirBoth | undefined;\n  const options = normalizeOptions(\n    typeof optionsOrCallback === \"function\" ? null : optionsOrCallback,\n  );\n  path = getValidatedPathToString(path);\n\n  if (!callback) throw new Error(\"No callback function supplied\");\n\n  validateEncoding(options?.encoding);\n\n  const { join, relative } = lazyPath();\n  const result: Array<string | Dirent> = [];\n  const dirs = [path];\n  let current: string | undefined;\n  (async () => {\n    while ((current = ArrayPrototypeShift(dirs)) !== undefined) {\n      try {\n        const entries = await collectReadDir(current);\n\n        for (let i = 0; i < entries.length; i++) {\n          const entry = entries[i];\n          if (options?.recursive && entry.isDirectory) {\n            ArrayPrototypePush(dirs, join(current, entry.name));\n          }\n","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/node/polyfills/_fs/_fs_readdir.ts#L152-L188","documentation":"fs.readdir(path, [options], callback) resolves its callback from optionsOrCallback (if a function) or maybeCallback; if neither is a function it throws the plain Error 'No callback function supplied' (no code). Note that unlike some fs APIs, path validation happens before this check, so a bad path throws first.","triggerScenarios":"fs.readdir('/tmp') with no second argument; fs.readdir('/tmp', { withFileTypes: true }) with options but no callback.","commonSituations":"Expecting readdir to return entries synchronously or as a promise while using the callback form; refactors between fs.promises.readdir and fs.readdir losing the trailing function.","solutions":["Use fs.promises.readdir(path, options) for await-style code","Otherwise append a callback: fs.readdir(path, (err, files) => { ... })","Check wrappers forward the callback as the final positional argument"],"exampleFix":"// before\nfs.readdir(dir, { recursive: true });\n\n// after\nconst files = await fs.promises.readdir(dir, { recursive: true });\n// or\nfs.readdir(dir, { recursive: true }, (err, files) => { if (err) throw err; });","handlingStrategy":"validation","validationCode":"if (typeof optionsOrCallback !== 'function' && typeof maybeCallback !== 'function') {\n  throw new Error('readdir requires a callback; use fs.promises.readdir for promises');\n}","typeGuard":"const isCallback = (v) => typeof v === 'function';","tryCatchPattern":null,"preventionTips":["Prefer fs.promises.readdir in async code","Keep the callback as the final positional argument in wrappers","Rely on TypeScript signatures to catch missing callbacks"],"tags":["node-compat","fs","readdir","callback","api-misuse"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}