http server Bind errors bypass middleware chain (logging/tracing/recovery not executed)
Title
http server Bind errors bypass middleware chain (logging/tracing/recovery not executed)
Description
In the current go-kratos HTTP server implementation, request binding (Bind) happens before middleware execution. This leads to a critical issue:
If an error occurs during the binding phase (e.g., invalid request format, missing fields, or even a panic like nil pointer dereference), the middleware chain is never executed.
As a result:
- Logging middleware is skipped
- Tracing middleware is skipped
- Metrics middleware is skipped
- Recovery middleware cannot catch panics
This effectively breaks observability and stability guarantees.
Steps to Reproduce
Create a HTTP handler with a request struct
Send an invalid request (e.g., malformed JSON or missing required fields)
Or trigger a panic inside binding (e.g., custom binder or pointer issue)
Observe that:
- No logs are generated
- No tracing span is recorded
- No metrics are emitted
- Panic is not recovered
Expected Behavior
Even if binding fails or panics occur:
- Middleware chain should still be executed
- Logging / tracing / metrics should capture the failure
- Recovery middleware should handle panics
Actual Behavior
- Binding errors short-circuit the request lifecycle
- Middleware chain is completely bypassed
- Observability is lost
- Panic may crash the process (depending on context)
Root Cause Analysis
From current behavior, it appears that:
Request → Bind → Handler → MiddlewareInstead of the more robust design:
Request → Middleware → Bind → HandlerBecause binding occurs before middleware, any failure at this stage prevents middleware from executing.
Suggested Solutions
Option 1: Move Bind into middleware stage (Recommended)
Make binding part of the middleware chain:
Request → Middleware (including Bind) → HandlerThis ensures:
- All errors are observable
- Recovery middleware can catch panics
- Consistent request lifecycle
Option 2: Wrap Bind with internal middleware-like handling
If moving Bind is not feasible:
Wrap binding logic with:
- logging
- tracing
- panic recovery
But this duplicates middleware responsibilities and is less clean.
Option 3: Provide hook / interceptor before Bind
Expose a hook like:
BeforeBind(ctx, req)So users can inject observability logic manually.
Option 4: Ensure recovery at the outermost layer
Guarantee that panic recovery exists outside Bind, even before middleware.
Additional Context
This issue has significant impact in production systems:
- Silent failures (no logs, no traces)
- Observability blind spots
- Difficult debugging
- Potential process crashes
Environment
- go-kratos version: (please fill)
- Go version: (please fill)
- OS: (please fill)
Summary
The current execution order makes the system fragile and non-observable in case of binding errors. Adjusting the lifecycle so middleware wraps the entire request (including Bind) would greatly improve robustness and observability.
Source: go-kratos/kratos