gofr-dev/gofr · error

failed to set key-value pair: %w

Error message

failed to set key-value pair: %w

What it means

NATS KV Set wraps failures from c.kv.Put with 'failed to set key-value pair: %w', preserving the JetStream cause. It means the write to the bucket failed — typically a connection, bucket-existence, or JetStream limits problem — rather than a data issue.

Source

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

	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 {
	span := c.addTrace(ctx, "delete", key)
	defer c.sendOperationStats(time.Now(), "DELETE", "delete", span, key)

	err := c.kv.Delete(key)
	if err != nil {
		if errors.Is(err, nats.ErrKeyNotFound) {
			return fmt.Errorf("%w: %s", errKeyNotFound, key)
		}

		return fmt.Errorf("failed to delete key: %w", err)
	}

View on GitHub (pinned to 187eb24962)

Solutions

  1. Read the wrapped cause to distinguish connection vs bucket vs size errors
  2. Ensure the bucket exists at startup (Create the KV bucket before use) and reconnect logic is in place
  3. Reduce value size or raise server max_payload if large values are intended
  4. Retry with backoff on transient connection errors

Example fix

// before
err := store.Set(ctx, key, bigBlob)
// after
if len(bigBlob) > maxPayload { return ErrValueTooLarge }
if err := store.Set(ctx, key, bigBlob); err != nil {
    return retry.WithBackoff(func() error { return store.Set(ctx, key, bigBlob) })
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight checks before Set
if len(value) > maxJetstreamPayload { return fmt.Errorf("value too large: %d bytes", len(value)) }
if _, err := js.KeyValue(cfg.Bucket); err != nil { return fmt.Errorf("bucket %q missing: %w", cfg.Bucket, err) }

Type guard

func isSetFailure(err error) bool { return err != nil && strings.Contains(err.Error(), "failed to set key-value pair") } // prefer keeping the raw error and errors.Unwrap

Try / catch

if err := store.Set(ctx, key, value); err != nil {
    if isTransient(errors.Unwrap(err)) {
        return retry.WithBackoff(func() error { return store.Set(ctx, key, value) })
    }
    return err
}

Prevention

When it happens

Trigger: c.kv.Put(key, []byte(value)) errors: bucket does not exist, NATS connection lost, JetStream publish fails due to max payload/message-size limits, no storage resources, or account lacks publish permission.

Common situations: Bucket deleted or never created, oversized values exceeding JetStream max payload, NATS server restart, closed/expired connection, disk-full on the server's file store.

Related errors


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