gofr-dev/gofr · error

handler error

Error message

handler error

What it means

errHandlerError (errors.go:20) is the sentinel used in the NATS client's message-fetch/consume path when the registered message handler fails or fetching the next message errors. It wraps handler failures so the consume loop can report them through Query/subscriber error handling. Exercised by TestClient_Query_MessageFetchError.

Source

Thrown at pkg/gofr/datasource/pubsub/nats/errors.go:20

import "errors"

var (
	// Client Errors.
	errServerNotProvided       = errors.New("client server address not provided")
	errSubjectsNotProvided     = errors.New("subjects not provided")
	errConsumerNotProvided     = errors.New("consumer name not provided")
	errConsumerCreationError   = errors.New("consumer creation error")
	errFailedToDeleteStream    = errors.New("failed to delete stream")
	errPublishError            = errors.New("publish error")
	errJetStreamNotConfigured  = errors.New("jStream is not configured")
	errJetStreamCreationFailed = errors.New("jStream creation failed")
	errJetStream               = errors.New("jStream error")
	errCreateStream            = errors.New("create stream error")
	errDeleteStream            = errors.New("delete stream error")
	errGetStream               = errors.New("get stream error")
	errCreateOrUpdateStream    = errors.New("create or update stream error")
	errHandlerError            = errors.New("handler error")
	errConnectionError         = errors.New("connection error")
	errSubscriptionError       = errors.New("subscription error")
)

View on GitHub (pinned to 187eb24962)

Solutions

  1. Make your message handler defensive: validate/decode payloads and return errors only for genuine failures.
  2. Check the wrapped cause to distinguish a handler bug from a fetch/consumer failure.
  3. Recreate or reset the consumer if it was deleted or detached server-side (`nats consumer info <stream> <consumer>`).
  4. Add dead-letter/NAK handling for poison messages instead of failing the loop repeatedly.

Example fix

// before: handler errors on bad payload
handler := func(ctx context.Context, m pubsub.Message) error {
    var o Order; return json.Unmarshal(m.Value(), &o)
}
// after: tolerate malformed messages
if err := json.Unmarshal(m.Value(), &o); err != nil {
    logger.Errorf("skipping malformed message: %v", err)
    return nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate handler behavior before registering
if handler == nil {
    return errors.New("message handler must not be nil")
}

Try / catch

handler := func(ctx context.Context, m pubsub.Message) error {
    defer func() {
        if r := recover(); r != nil {
            logger.Errorf("handler panic: %v", r)
        }
    }()
    return process(ctx, m)
}

Prevention

When it happens

Trigger: During Client.Query/subscription consumption: the user-supplied MessageHandler returns an error, or fetching a message from the JetStream consumer fails (message expired/deleted, consumer detached).

Common situations: Handler panics or returns errors on malformed payloads (JSON decode failures); messages redelivered after AckWait with consumers in a bad state; consumer deleted server-side while fetching.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/15668cee9d2e79bc. Report an issue: GitHub.