gofr-dev/gofr · warning

%w: %s

Error message

%w: %s

What it means

NATS KV Get translates nats.ErrKeyNotFound from the underlying bucket into this library's sentinel: fmt.Errorf("%w: %s", errKeyNotFound, key), producing 'key not found: <key>'. The %w wrap preserves errors.Is matching against the library's errKeyNotFound. Other KV errors take a different path ('failed to get key').

Source

Thrown at pkg/gofr/datasource/kv-store/nats/nats.go:116

		Bucket: c.configs.Bucket,
	})
	if err != nil {
		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

View on GitHub (pinned to 187eb24962)

Solutions

  1. Use errors.Is(err, errKeyNotFound) to branch on miss and provide a default/fetch-from-source path
  2. Verify bucket consistency between producers and consumers
  3. Extend the bucket TTL if legitimate keys expire
  4. Log the key from the message to debug naming mismatches

Example fix

// before
v, err := store.Get(ctx, key)
return v, err
// after
v, err := store.Get(ctx, key)
if errors.Is(err, kv.ErrKeyNotFound) { return loadFromDB(key) }
if err != nil { return err }
Defensive patterns

Strategy: fallback

Validate before calling

// validate key format and non-emptiness before Get
if key == "" || !keyRe.MatchString(key) { return fmt.Errorf("invalid key %q", key) }

Type guard

func IsKeyNotFound(err error) bool { return errors.Is(err, natskv.ErrKeyNotFound) }

Try / catch

v, err := store.Get(ctx, key)
if errors.Is(err, natskv.ErrKeyNotFound) {
    return loadFromSource(key) // miss path
}
if err != nil { return fmt.Errorf("get %s: %w", key, err) }

Prevention

When it happens

Trigger: c.kv.Get(key) returns nats.ErrKeyNotFound — the key has no entry in the JetStream bucket (never written, deleted, or TTL-expired).

Common situations: Expired keys (bucket MaxAge), reading keys written to another bucket, miss-heavy cache lookups, key naming typos.

Related errors


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