denoland/deno · error · Error

No callback function supplied

Error message

No callback function supplied

What it means

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.

Source

Thrown at ext/node/polyfills/_fs/_fs_readdir.ts:170

export function readdir(
  path: string | Buffer | URL,
  optionsOrCallback:
    | readDirOptions
    | string
    | readDirCallback
    | readDirCallbackDirent,
  maybeCallback?: readDirCallback | readDirCallbackDirent,
) {
  const callback =
    (typeof optionsOrCallback === "function"
      ? optionsOrCallback
      : maybeCallback) as readDirBoth | undefined;
  const options = normalizeOptions(
    typeof optionsOrCallback === "function" ? null : optionsOrCallback,
  );
  path = getValidatedPathToString(path);

  if (!callback) throw new Error("No callback function supplied");

  validateEncoding(options?.encoding);

  const { join, relative } = lazyPath();
  const result: Array<string | Dirent> = [];
  const dirs = [path];
  let current: string | undefined;
  (async () => {
    while ((current = ArrayPrototypeShift(dirs)) !== undefined) {
      try {
        const entries = await collectReadDir(current);

        for (let i = 0; i < entries.length; i++) {
          const entry = entries[i];
          if (options?.recursive && entry.isDirectory) {
            ArrayPrototypePush(dirs, join(current, entry.name));
          }

View on GitHub (pinned to 89f33cbef2)

Solutions

  1. Use fs.promises.readdir(path, options) for await-style code
  2. Otherwise append a callback: fs.readdir(path, (err, files) => { ... })
  3. Check wrappers forward the callback as the final positional argument

Example fix

// before
fs.readdir(dir, { recursive: true });

// after
const files = await fs.promises.readdir(dir, { recursive: true });
// or
fs.readdir(dir, { recursive: true }, (err, files) => { if (err) throw err; });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof optionsOrCallback !== 'function' && typeof maybeCallback !== 'function') {
  throw new Error('readdir requires a callback; use fs.promises.readdir for promises');
}

Type guard

const isCallback = (v) => typeof v === 'function';

Prevention

When it happens

Trigger: fs.readdir('/tmp') with no second argument; fs.readdir('/tmp', { withFileTypes: true }) with options but no callback.

Common situations: 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.

Related errors


AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16). Data as JSON: /api/errors/ee547bf958448ca8. Report an issue: GitHub.