Skip to content

Commit 66d6575

Browse files
committed
fix(api): move defect handler to outermost middleware position
1 parent d6cb8f9 commit 66d6575

2 files changed

Lines changed: 16 additions & 7 deletions

File tree

apps/api/src/index.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,25 @@ const db = createDatabase(DATABASE_URL)
4141
/** Catches Effect defects (unexpected errors) and returns a proper JSON 500 response. */
4242
const withDefectHandler = HttpMiddleware.make((app) =>
4343
app.pipe(
44-
Effect.catchAllDefect(() =>
45-
Effect.succeed(formatApiError(new Error('internal defect'))),
44+
Effect.catchAllDefect((defect) =>
45+
Effect.gen(function* () {
46+
const message = defect instanceof Error ? defect.message : String(defect)
47+
yield* Effect.logError(`Unhandled defect: ${message}`)
48+
return formatApiError(new Error('internal defect'))
49+
}),
4650
),
4751
),
4852
)
4953

50-
// Production pipeline: connection drain is outermost so it gates all requests
54+
// Production pipeline: defect handler is outermost so it catches defects from
55+
// any middleware layer (auth, rate-limit, etc.), not just the router.
5156
const AppLive = ApiRouter.pipe(
52-
withDefectHandler,
5357
withConnectionDrain,
5458
withRateLimit,
5559
withAuth,
5660
withRequestId,
5761
withSecurityHeaders,
62+
withDefectHandler,
5863
HttpServer.serve(),
5964
)
6065

apps/api/src/server.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,14 @@ export const ApiRouter = HttpRouter.empty.pipe(
4545
/** Catches Effect defects (unexpected errors) and returns a proper JSON 500 response. */
4646
const withDefectHandler = HttpMiddleware.make((app) =>
4747
app.pipe(
48-
Effect.catchAllDefect(() =>
49-
Effect.succeed(formatApiError(new Error('internal defect'))),
48+
Effect.catchAllDefect((defect) =>
49+
Effect.gen(function* () {
50+
const message = defect instanceof Error ? defect.message : String(defect)
51+
yield* Effect.logError(`Unhandled defect: ${message}`)
52+
return formatApiError(new Error('internal defect'))
53+
}),
5054
),
5155
),
5256
)
5357

54-
export const AppLive = ApiRouter.pipe(withDefectHandler, withConnectionDrain, withRateLimit, withRequestId, withSecurityHeaders, HttpServer.serve())
58+
export const AppLive = ApiRouter.pipe(withConnectionDrain, withRateLimit, withRequestId, withSecurityHeaders, withDefectHandler, HttpServer.serve())

0 commit comments

Comments
 (0)