Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@louisinger
Copy link
Collaborator

@louisinger louisinger commented Nov 10, 2025

Revert the gRPC panic.go interceptor + return an INTERNAL_ERROR in case of recovery.

@altafan please review

Summary by CodeRabbit

  • Bug Fixes
    • Improved runtime stability by adding panic recovery for request handling so unexpected panics are caught and converted to a standardized internal error response.
    • Consistent error and stack-trace logging added to aid diagnostics while preserving normal request behavior when no panic occurs.

@louisinger louisinger requested a review from altafan November 10, 2025 09:19
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Walkthrough

Adds unary and stream gRPC panic-recovery interceptors and integrates them into the interceptor chains; panics during request handling are recovered, logged with stack traces, and converted into a standardized gRPC INTERNAL error.

Changes

Cohort / File(s) Summary
Panic Recovery Implementation
internal/interface/grpc/interceptors/panic.go
Implements unaryPanicRecoveryInterceptor() and streamPanicRecoveryInterceptor() that defer/recover from panics, log the panic and runtime/debug.Stack(), and return a standardized somethingWentWrong INTERNAL gRPC error on panic.
Interceptor Chain Integration
internal/interface/grpc/interceptors/interceptor.go
Adds the new panic recovery interceptors into the unary and stream interceptor chains so panics are wrapped by recovery logic during gRPC request handling.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GRPCServer as gRPC Server
    participant InterceptorChain as Interceptor Chain
    participant PanicInterceptor as Panic Recovery Interceptor
    participant Handler as Request Handler
    participant Logger as Logger

    Client->>GRPCServer: Send Request
    GRPCServer->>InterceptorChain: Invoke Chain (includes PanicInterceptor)
    
    rect rgb(245,250,255)
    Note over PanicInterceptor: defer recover() & capture stack
    PanicInterceptor->>Handler: Call Handler
    end

    alt Handler completes normally
        Handler-->>PanicInterceptor: Response
        PanicInterceptor-->>Client: Response
    else Handler panics
        Handler->>PanicInterceptor: panic()
        PanicInterceptor->>Logger: Log panic + stack trace
        Logger-->>PanicInterceptor: Logged
        PanicInterceptor-->>Client: Return INTERNAL error (somethingWentWrong)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to correct grpc interceptor signatures for unary and stream.
  • Verify somethingWentWrong error definition and mapping to gRPC INTERNAL.
  • Confirm logging level/format and use of runtime/debug.Stack() does not leak sensitive data.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Panic interceptor' is vague and generic, using non-descriptive terminology that doesn't convey the specific implementation or behavioral change of the changeset. Consider a more descriptive title that clarifies the change, such as 'Implement panic recovery interceptors with INTERNAL_ERROR handling' or 'Add panic recovery to gRPC interceptor chains'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66b77ea and e2f629e.

📒 Files selected for processing (1)
  • internal/interface/grpc/interceptors/panic.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/interface/grpc/interceptors/panic.go (1)
pkg/errors/errors.go (1)
  • INTERNAL_ERROR (208-208)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: unit tests
  • GitHub Check: Build and Scan
  • GitHub Check: integration tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/interface/grpc/interceptors/interceptor.go (1)

11-16: Move panic interceptor to the start of the chain for complete protection.

The panic interceptor is currently the last (innermost) in the chain, which means it only catches panics from the handler itself. Panics in errorConverter, unaryMacaroonAuthHandler, or unaryLogger will not be caught and will still crash the server.

Apply this diff to move the panic interceptor to the outermost position:

 func UnaryInterceptor(svc *macaroons.Service) grpc.ServerOption {
 	return grpc.UnaryInterceptor(middleware.ChainUnaryServer(
+		unaryPanicRecoveryInterceptor(),
 		unaryLogger,
 		unaryMacaroonAuthHandler(svc),
 		errorConverter,
-		unaryPanicRecoveryInterceptor(),
 	))
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e02dd66 and fe070b8.

📒 Files selected for processing (2)
  • internal/interface/grpc/interceptors/interceptor.go (2 hunks)
  • internal/interface/grpc/interceptors/panic.go (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/interface/grpc/interceptors/panic.go (1)
pkg/errors/errors.go (1)
  • INTERNAL_ERROR (208-208)
🔇 Additional comments (4)
internal/interface/grpc/interceptors/panic.go (4)

1-12: LGTM!

The package comment clearly describes the purpose, and the imports are appropriate for panic recovery with stack trace logging.


14-14: LGTM!

The generic error message appropriately avoids leaking internal details to clients, while the panic value is preserved in metadata for debugging.


33-35: LGTM!

The handler invocation and return pattern is correct. The named return parameters ensure the error set in the defer block is properly returned when a panic occurs.


55-57: LGTM!

The stream handler invocation follows the correct pattern, with the named return parameter ensuring panic-generated errors are properly returned.

Comment on lines 21 to 31
defer func() {
if r := recover(); r != nil {
log.Errorf("panic-recovery middleware recovered from panic: %v", r)
log.Debugf(
"panic-recovery middleware recovered from panic: %v", string(debug.Stack()),
)
err = somethingWentWrong.WithMetadata(map[string]any{
"error": r,
})
}
}()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Log stack trace at Error level for production visibility.

The stack trace is currently logged only at Debug level, which may be disabled in production. When investigating production panics, the stack trace is critical for diagnosis.

Apply this diff:

 		defer func() {
 			if r := recover(); r != nil {
 				log.Errorf("panic-recovery middleware recovered from panic: %v", r)
-				log.Debugf(
-					"panic-recovery middleware recovered from panic: %v", string(debug.Stack()),
-				)
+				log.Errorf("Stack trace: %s", string(debug.Stack()))
 				err = somethingWentWrong.WithMetadata(map[string]any{
 					"error": r,
 				})
 			}
 		}()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
defer func() {
if r := recover(); r != nil {
log.Errorf("panic-recovery middleware recovered from panic: %v", r)
log.Debugf(
"panic-recovery middleware recovered from panic: %v", string(debug.Stack()),
)
err = somethingWentWrong.WithMetadata(map[string]any{
"error": r,
})
}
}()
defer func() {
if r := recover(); r != nil {
log.Errorf("panic-recovery middleware recovered from panic: %v", r)
log.Errorf("Stack trace: %s", string(debug.Stack()))
err = somethingWentWrong.WithMetadata(map[string]any{
"error": r,
})
}
}()
🤖 Prompt for AI Agents
In internal/interface/grpc/interceptors/panic.go around lines 21-31, the defer
recovery currently logs the panic message at Error level but only logs the stack
trace at Debug level; change it to log the stack trace at Error level so it's
visible in production (keep or optionally also log at Debug), and include the
stack trace in the error metadata as well. Specifically, capture debug.Stack()
into a variable, call log.Errorf with both the panic value and the stack trace,
and add the stack string to the somethingWentWrong.WithMetadata map (e.g.,
"stack": stack) so the error returned contains the stack trace.

@tiero tiero requested a review from sekulicd November 10, 2025 10:05
@altafan altafan merged commit 2644f63 into arkade-os:master Nov 10, 2025
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants