error-handler

command module
v0.0.0-...-1b08604 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 11 Imported by: 0

README

Error Handler Example

This example demonstrates the WithErrorHandler ServerOption feature of sebuf, which allows you to customize how errors are handled and returned to clients.

Overview

The ErrorHandler function is called whenever an error occurs during request processing. You can use it to:

  1. Log errors without modifying the response
  2. Add custom headers to error responses
  3. Set custom HTTP status codes for specific error types
  4. Return custom error response bodies (proto.Message)
  5. Write directly to the response for full control

Quick Start

# Generate code and build
make all

# Run the server
make run

Error Handler Examples

1. Logging Only

Just log errors without changing the response:

func LoggingErrorHandler(w http.ResponseWriter, r *http.Request, err error) proto.Message {
    log.Printf("[%s] Error: %v", r.Header.Get("X-Request-ID"), err)
    return nil // Use default response
}
2. Add Custom Headers

Add tracking headers while keeping default response:

func HeaderErrorHandler(w http.ResponseWriter, r *http.Request, err error) proto.Message {
    w.Header().Set("X-Error-ID", uuid.NewString())
    w.Header().Set("X-Error-Timestamp", time.Now().UTC().Format(time.RFC3339))
    return nil // Use default response with custom headers
}
3. Custom Status Codes

Override the default HTTP status codes:

func StatusCodeErrorHandler(w http.ResponseWriter, r *http.Request, err error) proto.Message {
    var valErr *sebufhttp.ValidationError
    if errors.As(err, &valErr) {
        w.WriteHeader(http.StatusUnprocessableEntity) // 422 instead of 400
    }
    return nil // Framework marshals default error with custom status
}
4. Custom Response Body

Return a custom protobuf message as the error response:

func CustomBodyErrorHandler(w http.ResponseWriter, r *http.Request, err error) proto.Message {
    return &models.CustomError{
        Code:      "ERR001",
        Message:   err.Error(),
        RequestId: r.Header.Get("X-Request-ID"),
        Timestamp: time.Now().Unix(),
    }
}
5. Full Control

Write directly to the response for complete control:

func FullControlErrorHandler(w http.ResponseWriter, r *http.Request, err error) proto.Message {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusInternalServerError)
    w.Write([]byte(`{"error": "custom format"}`))
    return nil // Framework won't write anything since we already called Write()
}

Error Types

The handler receives the error and can inspect it using errors.As():

// Check for validation errors (HTTP 400)
var valErr *sebufhttp.ValidationError
if errors.As(err, &valErr) {
    // Handle validation error
    for _, v := range valErr.Violations {
        fmt.Printf("Field %s: %s\n", v.Field, v.Description)
    }
}

// Check for handler errors (HTTP 500)
var handlerErr *sebufhttp.Error
if errors.As(err, &handlerErr) {
    // Handle service error
    fmt.Printf("Error: %s\n", handlerErr.Message)
}

// Check for custom error types
var notFound *ErrNotFound
if errors.As(err, &notFound) {
    // Handle not found error
}

Registration

Register your service with a custom error handler:

services.RegisterUserServiceServer(server,
    services.WithMux(mux),
    services.WithErrorHandler(myErrorHandler),
)

Test Commands

# Create a user (success)
curl -X POST http://localhost:8080/api/v1/users \
  -H "Content-Type: application/json" \
  -H "X-Request-ID: test-123" \
  -d '{"name": "John Doe", "email": "john@example.com"}'

# Validation error (short name)
curl -X POST http://localhost:8080/api/v1/users \
  -H "Content-Type: application/json" \
  -d '{"name": "J", "email": "invalid-email"}'

# Not found error
curl -v http://localhost:8080/api/v1/users/non-existent-id

# With request ID header
curl -v http://localhost:8080/api/v1/users/non-existent-id \
  -H "X-Request-ID: my-trace-id-456"

Default Behavior

When no ErrorHandler is configured, or when the handler returns nil:

  • ValidationError: Returns HTTP 400 with the ValidationError protobuf message
  • Other errors: Returns HTTP 500 with the Error protobuf message

The response format (JSON or protobuf) matches the request's Content-Type header.

Documentation

Overview

Package main demonstrates the WithErrorHandler feature of sebuf.

This example shows all the different ways you can use the ErrorHandler:

  1. Logging errors without modifying the response
  2. Adding custom headers to error responses
  3. Setting custom HTTP status codes
  4. Returning custom error response bodies
  5. Writing directly to the response (full control)

Run: go run main.go Then test with curl commands shown at startup.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL