caolan/async · error · Error
task callback must be a function
Error message
task callback must be a function
What it means
When pushing tasks to a queue (or cargo), any non-null callback supplied after the task data must be a function; q.push(data, 'done') or push(data, 42) throws immediately. This validates the per-task completion callback before scheduling work.
Source
Thrown at lib/internal/queue.js:50
handler(...args)
}
events[event].push(handleAndRemove)
}
function off (event, handler) {
if (!event) return Object.keys(events).forEach(ev => events[ev] = [])
if (!handler) return events[event] = []
events[event] = events[event].filter(ev => ev !== handler)
}
function trigger (event, ...args) {
events[event].forEach(handler => handler(...args))
}
var processingScheduled = false;
function _insert(data, insertAtFront, rejectOnError, callback) {
if (callback != null && typeof callback !== 'function') {
throw new Error('task callback must be a function');
}
q.started = true;
var res, rej;
function promiseCallback (err, ...args) {
// we don't care about the error, let the global error handler
// deal with it
if (err) return rejectOnError ? rej(err) : res()
if (args.length <= 1) return res(args[0])
res(args)
}
var item = q._createTaskItem(
data,
rejectOnError ? promiseCallback :
(callback || promiseCallback)
);
View on GitHub (pinned to 13dfaf13f3)
Solutions
- Pass a function as the second argument: q.push(task, (err) => {...})
- Omit the second argument entirely if no per-task callback is needed
- Check that the variable holding the callback actually holds a function
- Use q.drain / promise-returning push (pushAsync) instead of ad-hoc callbacks
Example fix
// before
q.push(task, 'handleResult');
// after
q.push(task, (err) => { if (err) console.error(err); }); Defensive patterns
Strategy: type-guard
Validate before calling
const isCallback = (v) => v == null || typeof v === 'function';
if (!isCallback(cb)) throw new TypeError('task callback must be a function'); Type guard
function isFunction(v) {
return typeof v === 'function';
} Try / catch
try {
q.push(task, cb);
} catch (err) {
if (String(err.message).includes('callback must be a function')) {
console.error('Second argument to push must be a function or omitted');
} else throw err;
} Prevention
- Only pass functions (or nothing) as the second argument to push/unshift
- Use pushAsync with promises for per-task completion
- Type-check callback variables after refactors
When it happens
Trigger: q.push(task, undefined-as-string variables), passing a truthy non-function such as the string 'cb', a thenable, or an object where a function was intended: q.push(item, somePromise). Also q.unshift with the same mistake.
Common situations: Argument-order mistakes when wrapping push, refactors where the callback variable was reassigned, passing options object as second arg mistakenly believing it's a callback, TypeScript types bypassed with any.
Related errors
- Concurrency must not be zero
- expected a function
- Invalid arguments for async.retry
- async.auto task `${key}` has a non-existent dependency `${de
- async.auto cannot execute tasks due to a recursive dependenc
AI-assisted analysis of caolan/async@13dfaf13f3 (2026-08-28).
Data as JSON: /api/errors/597da09158f8e4df.
Report an issue: GitHub.