{"record":{"id":"924769b52f049f1a","repo":"honojs/hono","slug":"context-is-not-finalized-did-you-forget-to-return","errorCode":null,"errorMessage":"Context is not finalized. Did you forget to return a Response object or `await next()`?","messagePattern":"Context is not finalized\\. Did you forget to return a Response object or `await next\\(\\)`\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/hono-base.ts","lineNumber":457,"sourceCode":"      }\n\n      return res instanceof Promise\n        ? res\n            .then(\n              (resolved: Response | undefined) =>\n                resolved || (c.finalized ? c.res : this.#notFoundHandler(c))\n            )\n            .catch((err: Error) => this.#handleError(err, c))\n        : (res ?? this.#notFoundHandler(c))\n    }\n\n    const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler)\n\n    return (async () => {\n      try {\n        const context = await composed(c)\n        if (!context.finalized) {\n          throw new Error(\n            'Context is not finalized. Did you forget to return a Response object or `await next()`?'\n          )\n        }\n\n        return context.res\n      } catch (err) {\n        return this.#handleError(err, c)\n      }\n    })()\n  }\n\n  /**\n   * `.fetch()` will be entry point of your app.\n   *\n   * @see {@link https://hono.dev/docs/api/hono#fetch}\n   *\n   * @param {Request} request - request Object of request\n   * @param {Env} env - env Object","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/honojs/hono/blob/e2740d5a1bd0b4254e517e3af8b60789284bc7bd/src/hono-base.ts#L439-L475","documentation":"This error is thrown by Hono's dispatcher when, after all matching middleware and handlers run, the Context has not been finalized — meaning no Response object was ever set. It almost always means a middleware or handler completed without returning a Response and without awaiting next(), so the composed chain ended with an unresolved context.","triggerScenarios":"A handler or middleware that returns undefined (no return statement), a middleware that forgets `await next()`, an early-return guard path (e.g. auth check) that returns nothing, or throwing/rejecting inside a custom middleware that is swallowed so no response is produced.","commonSituations":"Adding an authentication/validation middleware that returns early on failure without returning a Response; refactoring a handler and dropping the return; using a middleware that calls next() without await (fire-and-forget); conditional branches where one path returns c.json() and another falls through.","solutions":["Make every handler and middleware return a Response (e.g. `return c.json({...})`) on all code paths","In middleware, ensure you `await next()` when not short-circuiting, and return a Response (e.g. `return c.text('Unauthorized', 401)`) when you do","Audit early-return branches (auth, validation, rate limits) to confirm each returns something","If you wrapped the app in custom compose/error logic, verify the errorHandler returns a Response"],"exampleFix":"// before\napp.use('/admin/*', async (c, next) => {\n  if (!c.req.header('Authorization')) return // falls through, nothing set\n  await next()\n})\n// after\napp.use('/admin/*', async (c, next) => {\n  if (!c.req.header('Authorization')) {\n    return c.text('Unauthorized', 401)\n  }\n  await next()\n})","handlingStrategy":"validation","validationCode":"// Ensure every guard branch returns\napp.use('/api/*', async (c, next) => {\n  const auth = c.req.header('Authorization')\n  if (!auth) return c.text('Unauthorized', 401)\n  await next()\n})","typeGuard":"null","tryCatchPattern":"try {\n  const res = await app.request(req)\n} catch (e) {\n  if (e instanceof Error && /not finalized/.test(e.message)) {\n    // a middleware/handler fell through; add missing return/await next()\n  }\n}","preventionTips":["Always return a Response or c.json/c.text result from handlers on every branch","Use `await next()` in middleware unless short-circuiting with a returned Response","Enable TypeScript's noImplicitReturns or add ESLint rules to catch fall-through paths"],"tags":["hono","middleware","response","control-flow"],"backgroundTag":"middleware-no-response-returned","analyzedSha":"e2740d5a1bd0b4254e517e3af8b60789284bc7bd","analyzedAt":"2026-08-28T10:18:08.750Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}