{"record":{"id":"6edbdf3f6396df15","repo":"avajs/ava","slug":"t-throwsasync-must-be-called-with-a-function-o","errorCode":null,"errorMessage":"`t.throwsAsync()` must be called with a function or promise","messagePattern":"`t\\.throwsAsync\\(\\)` must be called with a function or promise","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"lib/assert.js","lineNumber":474,"sourceCode":"\t\t\t\tthrow fail(error);\n\t\t\t}\n\t\t});\n\n\t\tthis.throwsAsync = withSkip(async (...args) => {\n\t\t\tlet [thrower, expectations, message] = args;\n\n\t\t\ttry {\n\t\t\t\tassertMessage(message, 't.throwsAsync()');\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait thrower;\n\t\t\t\t} catch {}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (typeof thrower !== 'function' && !isPromise(thrower)) {\n\t\t\t\tthrow fail(new AssertionError('`t.throwsAsync()` must be called with a function or promise', {\n\t\t\t\t\tassertion: 't.throwsAsync()',\n\t\t\t\t\tformattedDetails: [formatWithLabel('Called with:', thrower)],\n\t\t\t\t}));\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\texpectations = validateExpectations('t.throwsAsync()', expectations, args.length, experiments);\n\t\t\t} catch (error) {\n\t\t\t\ttry {\n\t\t\t\t\tawait thrower;\n\t\t\t\t} catch {}\n\n\t\t\t\tthrow fail(error);\n\t\t\t}\n\n\t\t\tconst handlePromise = async (promise, wasReturned) => {\n\t\t\t\t// Record the stack before it gets lost in the promise chain.\n\t\t\t\tconst assertionStack = getAssertionStack();","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/avajs/ava/blob/bbfd946322fdeca2b547a691d947fb4e18c0c67f/lib/assert.js#L456-L492","documentation":"AVA throws this fixed usage error when t.throwsAsync() is given a first argument that is neither a function nor a promise. t.throwsAsync() must observe a rejection from one of those two shapes; anything else (undefined, a value, an Error instance) cannot reject, so the library flags improper usage with 'Called with:' detail.","triggerScenarios":"await t.throwsAsync(doAsync()) where doAsync throws synchronously before returning a promise; t.throwsAsync(await somePromise); t.throwsAsync() with no arguments; passing a rejected Error value directly.","commonSituations":"Calling an async function that throws before its first await so no promise is produced; forgetting to await/pass the promise; wrapping the wrong expression in the assertion.","solutions":["Pass a thunk: await t.throwsAsync(() => asyncFn()).","Pass the promise itself: await t.throwsAsync(somePromise).","If the call throws synchronously, use t.throws(() => ...) instead."],"exampleFix":"// before\nawait t.throwsAsync(asyncFn()); // throws synchronously, returns nothing\n// after\nawait t.throwsAsync(() => asyncFn());","handlingStrategy":"type-guard","validationCode":"const throwerVal = typeof thrower === 'function' ? thrower : thrower;\nif (typeof throwerVal !== 'function' && !(throwerVal && typeof throwerVal.then === 'function')) {\n  throw new TypeError('t.throwsAsync expects a function or promise; got ' + typeof throwerVal);\n}","typeGuard":"const isValidThrower = (v) => typeof v === 'function' || (v != null && typeof v.then === 'function');","tryCatchPattern":"try {\n  await t.throwsAsync(thrower);\n} catch (err) {\n  if (/must be called with a function or promise/.test(err.message)) {\n    t.fail('Pass a thunk or a promise: t.throwsAsync(() => asyncFn())');\n  } else { throw err; }\n}","preventionTips":["Wrap async calls in arrow functions: () => asyncFn(), never asyncFn().","If the call throws synchronously, capture it with t.throws(() => ...) instead.","Never pass Error instances or plain values as the thrower."],"tags":["assertion","ava","type-error","usage-error","promise"],"backgroundTag":"assertion-requires-function","analyzedSha":"bbfd946322fdeca2b547a691d947fb4e18c0c67f","analyzedAt":"2026-09-02T01:24:43.834Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}