caolan/async · error · Error
arity is undefined
Error message
arity is undefined
What it means
awaitify wraps a callback-style function so it can return a promise when no callback is supplied. It derives the callback position from arity; if the passed arity argument is falsy AND asyncFn.length is 0, there is no way to know where the callback belongs, so it throws. This guards against wrapping functions that declare no parameters.
Source
Thrown at lib/internal/awaitify.js:5
// conditionally promisify a function.
// only return a promise if a callback is omitted
export default function awaitify (asyncFn, arity) {
if (!arity) arity = asyncFn.length;
if (!arity) throw new Error('arity is undefined')
function awaitable (...args) {
if (typeof args[arity - 1] === 'function') {
return asyncFn.apply(this, args)
}
return new Promise((resolve, reject) => {
args[arity - 1] = (err, ...cbArgs) => {
if (err) return reject(err)
resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0])
}
asyncFn.apply(this, args)
})
}
return awaitable
}
View on GitHub (pinned to 13dfaf13f3)
Solutions
- Declare the callback as a named parameter so asyncFn.length is > 0: function (callback) {...}
- Wrap the function to expose correct arity: const wrapped = (cb) => original(cb)
- Upgrade async (newer versions handle rest-arg functions better)
- Call the callback-taking function directly instead of via promisification
Example fix
// before const fn = (...args) => legacy(...args); // length 0 // after const fn = (callback) => legacy(callback); // length 1
Defensive patterns
Strategy: type-guard
Validate before calling
const isPromisifiable = (fn) => typeof fn === 'function' && fn.length > 0;
Type guard
function hasCallbackArity(fn) {
return typeof fn === 'function' && fn.length > 0;
} Try / catch
try {
const promisified = awaitify(fn);
} catch (err) {
if (String(err.message) === 'arity is undefined') {
console.error('Function must declare a callback parameter');
} else throw err;
} Prevention
- Avoid rest-only (...args) signatures for functions you promisify
- Declare the callback as the last named parameter
- Prefer async.util promisification on explicitly-shaped functions
When it happens
Trigger: Internally when a wrapped function has zero declared parameters (e.g. (...args) => {} rest-only functions have length 0) and no explicit arity is given, e.g. a task function written as function (...args) {} passed to a promisified API.
Common situations: Using rest-parameter task functions with async promisification, minified functions compiled to rest args, passing a wrapper around the real callback-taking function.
Related errors
- async.auto task `${key}` has a non-existent dependency `${de
- async.auto cannot execute tasks due to a recursive dependenc
- could not parse args in autoInject Source: ${src}
- autoInject task functions require explicit parameters.
- concurrency limit cannot be less than 1
AI-assisted analysis of caolan/async@13dfaf13f3 (2026-08-28).
Data as JSON: /api/errors/2af342996c877ea3.
Report an issue: GitHub.