gofr-dev/gofr · error
failed to get key: %w
Error message
failed to get key: %w
What it means
NATS KV Get wraps any non-not-found error from the underlying bucket read with 'failed to get key: %w'. Unlike the key-not-found path, this indicates a real failure talking to JetStream/NATS (connection, permissions, bucket state), with the NATS cause preserved via %w.
Source
Thrown at pkg/gofr/datasource/kv-store/nats/nats.go:119
c.logger.Errorf("error while creating/accessing KV bucket: %v", err)
return
}
c.kv = kv
c.logger.Infof("successfully connected to NATS-KV Store at %s:%s ", c.configs.Server, c.configs.Bucket)
}
func (c *Client) Get(ctx context.Context, key string) (string, error) {
span := c.addTrace(ctx, "get", key)
defer c.sendOperationStats(time.Now(), "GET", "get", span, key)
entry, err := c.kv.Get(key)
if err != nil {
if errors.Is(err, nats.ErrKeyNotFound) {
return "", fmt.Errorf("%w: %s", errKeyNotFound, key)
}
return "", fmt.Errorf("failed to get key: %w", err)
}
return string(entry.Value()), nil
}
func (c *Client) Set(ctx context.Context, key, value string) error {
span := c.addTrace(ctx, "set", key)
defer c.sendOperationStats(time.Now(), "SET", "set", span, key, value)
_, err := c.kv.Put(key, []byte(value))
if err != nil {
return fmt.Errorf("failed to set key-value pair: %w", err)
}
return nil
}
func (c *Client) Delete(ctx context.Context, key string) error {View on GitHub (pinned to 187eb24962)
Solutions
- Inspect the wrapped cause (errors.Unwrap / %w) to identify the NATS error
- Add reconnect handling: retry after the NATS client reconnects (nc.Options with ReconnectWait) or recreate the KV view
- Verify account permissions grant read on the KV bucket
- Check server logs for JetStream stream/bucket deletion events
Example fix
// before
v, err := store.Get(ctx, key)
return v, err
// after
v, err := store.Get(ctx, key)
if err != nil && !errors.Is(err, kv.ErrKeyNotFound) {
return retry.WithBackoff(func() error { _, err = store.Get(ctx, key); return err })
} Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: connection + bucket readable
if store == nil || !store.connected { return errors.New("nats kv not connected") }
_, err := js.KeyValue(cfg.Bucket)
if err != nil { return fmt.Errorf("bucket unreadable: %w", err) } Type guard
func IsKeyNotFound(err error) bool { return errors.Is(err, natskv.ErrKeyNotFound) } // exclude miss before retrying Try / catch
v, err := store.Get(ctx, key)
if err != nil && !errors.Is(err, natskv.ErrKeyNotFound) {
err = retry.WithBackoff(func() error { v, err = store.Get(ctx, key); return err })
}
return v, err Prevention
- Never retry on key-not-found — retry only real failures
- Enable NATS auto-reconnect and wait for reconnect before retrying
- Verify account permissions for the bucket
- Alert on repeated 'failed to get key' wrapped causes
When it happens
Trigger: c.kv.Get(key) fails with errors other than nats.ErrKeyNotFound — connection dropped, bucket/stream deleted, JetStream unavailable, permission denied on the bucket.
Common situations: NATS server restart or network partition mid-operation, IAM/account lacking read on the bucket, bucket purged or nuked while the app runs.
Related errors
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/9b0eb17a75beb6c0.
Report an issue: GitHub.