benbjohnson/litestream · error

webdav url required

Error message

webdav url required

What it means

ReplicaClient.init lazily creates the underlying gowebdav client and requires the URL field to be set. This error is thrown when init is called on a ReplicaClient whose URL is empty — i.e. the client was constructed without a server URL (or via a code path that never parsed/populated it).

Source

Thrown at webdav/replica_client.go:106

	return ReplicaClientType
}

func (c *ReplicaClient) Init(ctx context.Context) error {
	_, err := c.init(ctx)
	return err
}

// init initializes the connection and returns the WebDAV client.
func (c *ReplicaClient) init(ctx context.Context) (_ *gowebdav.Client, err error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	if c.client != nil {
		return c.client, nil
	}

	if c.URL == "" {
		return nil, fmt.Errorf("webdav url required")
	}

	c.client = gowebdav.NewClient(c.URL, c.Username, c.Password)

	c.client.SetTimeout(c.Timeout)

	if err := c.client.Connect(); err != nil {
		c.client = nil
		return nil, fmt.Errorf("webdav: cannot connect to server: %w", err)
	}

	return c.client, nil
}

func (c *ReplicaClient) DeleteAll(ctx context.Context) error {
	client, err := c.init(ctx)
	if err != nil {
		return err

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Set c.URL (and credentials/path) before calling Init or any replica operation, or build the client with NewReplicaClientFromURL("webdav://host/path")
  2. Fix the config so the webdav replica block includes a 'url' key with scheme, host and path
  3. Ensure the config section is actually being parsed into the ReplicaClient (check key names/casing)
  4. Validate config at startup so an empty URL fails fast with a clear message

Example fix

// before
c := webdav.NewReplicaClient()
c.Path = "/dav/litestream"
// after
c, err := webdav.NewReplicaClientFromURL("webdav://user:pass@dav.example.com/dav/litestream")
Defensive patterns

Strategy: validation

Validate before calling

if client.URL == "" {
    return errors.New("webdav replica client requires a URL before Init")
}

Type guard

func (c *webdav.ReplicaClient) Configured() bool { return c.URL != "" }

Try / catch

if _, err := rc.Init(ctx); err != nil && strings.Contains(err.Error(), "webdav url required") {
    return fmt.Errorf("replica client built without URL — use NewReplicaClientFromURL: %w", err)
}

Prevention

When it happens

Trigger: Using the webdav ReplicaClient programmatically (webdav.NewReplicaClient()) without setting the URL field before any operation (Init, LTXFiles, Write, DeleteAll); deserializing config that omitted the URL.

Common situations: Building the client in code and forgetting to populate fields that the URL parser normally fills; loading a replica config section with a missing 'url' key; constructing the struct manually instead of via NewReplicaClientFromURL.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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