benbjohnson/litestream · error

invalid scheme for NATS replica: %s

Error message

invalid scheme for NATS replica: %s

What it means

After successfully parsing c.URL, newNATSReplicaClientFromConfig verifies the scheme equals 'nats'. Any other scheme (s3, abs, file, sftp, ...) means the URL describes a different backend, so this error reports the offending scheme verbatim.

Source

Thrown at cmd/litestream/main.go:1922

	client.URL = webdavURL
	client.Username = username
	client.Password = password
	client.Path = path

	return client, nil
}

// newNATSReplicaClientFromConfig returns a new instance of nats.ReplicaClient built from config.
func newNATSReplicaClientFromConfig(c *ReplicaConfig, _ *litestream.Replica) (_ *nats.ReplicaClient, err error) {
	// Parse URL if provided to extract bucket name and server URL
	var url, bucket string
	if c.URL != "" {
		scheme, host, bucketPath, err := litestream.ParseReplicaURL(c.URL)
		if err != nil {
			return nil, fmt.Errorf("invalid NATS URL: %w", err)
		}
		if scheme != "nats" {
			return nil, fmt.Errorf("invalid scheme for NATS replica: %s", scheme)
		}

		// Reconstruct URL without bucket path
		if host != "" {
			url = fmt.Sprintf("nats://%s", host)
		}

		// Extract bucket name from path
		if bucketPath != "" {
			bucket = strings.Trim(bucketPath, "/")
		}
	}

	// Use bucket from config if not extracted from URL
	if bucket == "" {
		bucket = c.Bucket
	}

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Change the URL scheme to 'nats://', e.g. 'nats://nats.example.com:4222/mybucket'
  2. Or change the replica type to match the scheme you actually intended
  3. Search the config for other replica blocks and ensure url schemes align with each block's type

Example fix

# before
- type: nats
  url: s3://mybucket/db
# after
- type: nats
  url: nats://nats.example.com:4222/mybucket
Defensive patterns

Strategy: validation

Validate before calling

if rep.Type == "nats" && rep.URL != "" {
    if scheme, _, _, err := litestream.ParseReplicaURL(rep.URL); err == nil && scheme != "nats" {
        return fmt.Errorf("nats replica %s: expected nats:// scheme, got %s", rep.Name, scheme)
    }
}

Type guard

func isNATSScheme(raw string) bool {
    scheme, _, _, err := litestream.ParseReplicaURL(raw)
    return err == nil && scheme == "nats"
}

Prevention

When it happens

Trigger: A nats replica whose 'url' uses a non-nats scheme, e.g. url: 's3://bucket/path' inside a type: nats block, or a typo like 'nats2://host/bucket'.

Common situations: Copy-pasting a replica URL from another backend's config into a nats replica block; swapping replica 'type' without updating the url scheme.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of benbjohnson/litestream@4ed7a308f6 (2026-09-06). Data as JSON: /api/errors/e02197df03e3d313. Report an issue: GitHub.