{"id":"09da3c790b0e2fad","repo":"koajs/koa","slug":"middleware-must-be-a-function","errorCode":null,"errorMessage":"middleware must be a function!","messagePattern":"middleware must be a function!","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/application.js","lineNumber":153,"sourceCode":"   * @api public\n   */\n\n  inspect () {\n    return this.toJSON()\n  }\n\n  /**\n   * Use the given middleware `fn`.\n   *\n   * Old-style middleware will be converted.\n   *\n   * @param {(context: Context) => Promise<any | void>} fn\n   * @return {Application} self\n   * @api public\n   */\n\n  use (fn) {\n    if (typeof fn !== 'function') { throw new TypeError('middleware must be a function!') }\n    debug('use %s', fn._name || fn.name || '-')\n    this.middleware.push(fn)\n    return this\n  }\n\n  /**\n   * Return a request handler callback\n   * for node's native http server.\n   *\n   * @return {Function}\n   * @api public\n   */\n\n  callback () {\n    const fn = this.compose(this.middleware)\n\n    if (!this.listenerCount('error')) this.on('error', this.onerror)\n","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/koajs/koa/blob/52d5e8ff5ac79f2479463b53df2999900ae95115/lib/application.js#L135-L171","documentation":"Thrown synchronously by app.use(fn) when the supplied value is not a function. Koa's middleware pipeline is composed entirely of functions (ctx, next) => Promise, so registering anything else (undefined, an object, a string) would break compose() at request time; instead Koa fails fast at registration. The check is intentionally primitive (typeof fn !== 'function') so it accepts both normal and async functions and rejects every other type. This is a programmer/usage error, not a runtime condition — it indicates a bug in wiring middleware.","triggerScenarios":"Calling app.use(undefined), app.use(null), app.use({}), or app.use(someObject) where a middleware factory returned undefined instead of a function. Common forms: app.use(router.routes()) when @koa/router is not imported or router is undefined; app.use(require('./middleware')) when the module forgot module.exports; app.use(bodyParser()) when body-parser is for Express (returns an object) instead of koa-bodyparser; spreading an array app.use(...middlewares) with an empty slot; conditional registration app.use(cond && mw) where cond is false yielding undefined.","commonSituations":"Mixing Express middleware (which returns objects/handlers) into a Koa app; forgetting to actually invoke a middleware factory (app.use(cors) vs app.use(cors())); typo'd or missing import so the symbol is undefined; dead-code/conditional registration that yields a falsy value; upgrading a middleware package whose API changed from returning a function to requiring invocation; circular import evaluating the middleware file before its export is assigned (value still undefined at use() time).","solutions":["Inspect the value passed to app.use: add console.log(typeof fn, fn) right before the call to identify which registration is non-function.","Verify each middleware import resolves to a function — check require('./x') is not undefined (missing/late module.exports) and that factories are invoked (e.g. bodyparser() not bodyparser).","Confirm you are using Koa-compatible middleware (koa-bodyparser, @koa/router, koa-cors), not Express middleware (body-parser, cors).","For conditional registration, guard with if (mw) app.use(mw) or use a default no-op: app.use(mw || ((ctx, next) => next())).","For router middleware, ensure @koa/router is imported and instantiated: const router = new Router(); app.use(router.routes()).","If importing from an ESM/CJS package that has a .default interop issue, read the actual export: const mw = mod.default || mod; app.use(mw)."],"exampleFix":"// before\nconst router = require('@koa/router')\napp.use(router.routes())           // router is the class, not an instance -> not a function\n\n// after\nconst Router = require('@koa/router')\nconst router = new Router()\nrouter.get('/', ctx => { ctx.body = 'hi' })\napp.use(router.routes())           // router.routes() now returns middleware","handlingStrategy":"type-guard","validationCode":"// Before registering middleware, validate the value is a function\nfunction register (app, mw, label = 'middleware') {\n  if (typeof mw !== 'function') {\n    throw new TypeError(`Cannot register ${label}: expected function, got ${mw === null ? 'null' : typeof mw}`)\n  }\n  app.use(mw)\n}\n\n// Usage: register(app, router.routes(), 'router.routes()')","typeGuard":"// Type guard for Koa middleware (sync or async)\nfunction isMiddleware (fn) {\n  return typeof fn === 'function'\n}\nfunction isAsyncMiddleware (fn) {\n  return typeof fn === 'function' && fn.constructor?.name === 'AsyncFunction'\n}\n\n// Narrow before use\nconst mw = (mod && (mod.default || mod))\nif (isMiddleware(mw)) app.use(mw)\nelse throw new Error(`import did not resolve to a middleware function`)\n\n// TypeScript:\n// const isMiddleware = (x: unknown): x is import('koa').Middleware =>\n//   typeof x === 'function'","tryCatchPattern":"// Synchronous TypeError — wrap registration loops to report the offending middleware\nfor (const [name, mw] of Object.entries(middlewares)) {\n  try {\n    app.use(mw)\n  } catch (e) {\n    if (e instanceof TypeError && /middleware must be a function/.test(e.message)) {\n      throw new Error(`Middleware \"${name}\" is not a function (got ${typeof mw}). Check its import/export.`)\n    }\n    throw e\n  }\n}","preventionTips":["Always invoke middleware factories: bodyparser(), cors(), router.routes() — a bare reference is rarely the middleware.","Lint for app.use() calls with non-call arguments; add a unit test that asserts every entry in the middleware list is a function before app.listen().","After every refactor of imports/re-exports, run the app once in a test harness — the throw is synchronous at registration, so a smoke test catches it instantly.","Keep a whitelist: only use middleware from packages whose name starts with koa- or @koa/; Express middleware (body-parser, morgan) will not satisfy the function contract.","Avoid conditional middleware with bare && — prefer explicit if blocks so an absent middleware is a conscious decision, not an accidental undefined."],"tags":["middleware","configuration","synchronous","type-error","usage-error"],"analyzedSha":"52d5e8ff5ac79f2479463b53df2999900ae95115","analyzedAt":"2026-08-03T17:44:17.351Z","schemaVersion":2}