benbjohnson/litestream · error

bucket required for gs replica URL

Error message

bucket required for gs replica URL

What it means

The GCS replica client factory requires the URL host to name the target bucket. NewReplicaClientFromURL returns this error when a gs:// replica URL has no host component, since the client would otherwise have no bucket to operate on.

Source

Thrown at gs/replica_client.go:63

	Path   string
}

// NewReplicaClient returns a new instance of ReplicaClient.
func NewReplicaClient() *ReplicaClient {
	return &ReplicaClient{
		logger: slog.Default().WithGroup(ReplicaClientType),
	}
}

func (c *ReplicaClient) SetLogger(logger *slog.Logger) {
	c.logger = logger.WithGroup(ReplicaClientType)
}

// NewReplicaClientFromURL creates a new ReplicaClient from URL components.
// This is used by the replica client factory registration.
func NewReplicaClientFromURL(scheme, host, urlPath string, query url.Values, userinfo *url.Userinfo) (litestream.ReplicaClient, error) {
	if host == "" {
		return nil, fmt.Errorf("bucket required for gs replica URL")
	}

	client := NewReplicaClient()
	client.Bucket = host
	client.Path = urlPath
	return client, nil
}

// Type returns "gs" as the client type.
func (c *ReplicaClient) Type() string {
	return ReplicaClientType
}

// Init initializes the connection to GS. No-op if already initialized.
func (c *ReplicaClient) Init(ctx context.Context) (err error) {
	c.mu.Lock()
	defer c.mu.Unlock()

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Include the bucket as the URL host: gs://my-bucket/path/to/replica.
  2. Ensure any env var used for the bucket name is set in the environment at litestream startup.
  3. Validate replica URLs at config-load time: for the gs scheme, require a non-empty host.
  4. Confirm credentials/service account separately; this error is purely about URL shape.

Example fix

// before (litestream.yml)
replicas:
  - url: gs:///backups/db
// after
replicas:
  - url: gs://my-bucket/backups/db
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(replicaURL)
if err != nil || u.Scheme != "gs" { return fmt.Errorf("not a gs replica URL") }
if u.Host == "" { return fmt.Errorf("bucket required for gs replica URL") }

Type guard

func validGSReplicaURL(u *url.URL) bool { return u != nil && u.Scheme == "gs" && u.Host != "" }

Try / catch

if _, err := NewReplicaClientFromURL("gs", u.Host, u.Path, u.Query(), u.User); err != nil {
    return fmt.Errorf("invalid gs replica URL %q: %w", replicaURL, err)
}

Prevention

When it happens

Trigger: Configuring a replica with URL gs:///some/path (empty host), gs:// with nothing after the scheme, or a templated config where the bucket variable expanded to empty, then instantiating via the URL factory.

Common situations: Missing bucket in the litestream.yml replica URL; ${GCS_BUCKET} unset at process start; copying an S3-style path-only URL into a gs:// scheme.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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