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

  1. Inspect the wrapped cause (errors.Unwrap / %w) to identify the NATS error
  2. Add reconnect handling: retry after the NATS client reconnects (nc.Options with ReconnectWait) or recreate the KV view
  3. Verify account permissions grant read on the KV bucket
  4. 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

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.