benbjohnson/litestream · error

host required for webdav replica URL

Error message

host required for webdav replica URL

What it means

When parsing a webdav:// replica URL, NewReplicaClientFromURL requires a host component to build the client's base URL. This error is thrown when the URL parses but contains no host (e.g. 'webdav:///path' or 'webdav://').

Source

Thrown at webdav/replica_client.go:78

// This is used by the replica client factory registration.
// URL format: webdav://[user[:password]@]host[:port]/path or webdavs://... (for HTTPS)
func NewReplicaClientFromURL(scheme, host, urlPath string, query url.Values, userinfo *url.Userinfo) (litestream.ReplicaClient, error) {
	client := NewReplicaClient()

	// Determine HTTP or HTTPS based on scheme
	httpScheme := "http"
	if scheme == "webdavs" {
		httpScheme = "https"
	}

	// Extract credentials from userinfo
	if userinfo != nil {
		client.Username = userinfo.Username()
		client.Password, _ = userinfo.Password()
	}

	if host == "" {
		return nil, fmt.Errorf("host required for webdav replica URL")
	}

	client.URL = fmt.Sprintf("%s://%s", httpScheme, host)
	client.Path = urlPath

	return client, nil
}

func (c *ReplicaClient) Type() string {
	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.

View on GitHub (pinned to 4ed7a308f6)

Solutions

  1. Add the host to the replica URL: webdav://user:pass@myserver.example.com:port/path
  2. Check the config with 'litestream replicas' or re-read the YAML — ensure nothing stripped the host (e.g. $HOST env var empty)
  3. Validate the URL with a parser before applying config: u, err := url.Parse(s); u.Host != ""
  4. If credentials live in the URL, confirm the '@' separates userinfo from the host and no '/' got misplaced

Example fix

// before
url: "webdav:///dav/litestream"
// after
url: "webdav://user:pass@dav.example.com:5005/dav/litestream"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(cfg.WebdavURL)
if err != nil { return err }
if u.Host == "" {
    return fmt.Errorf("webdav replica URL %q has no host", cfg.WebdavURL)
}

Type guard

func hasURLHost(raw string) bool {
    u, err := url.Parse(raw)
    return err == nil && u.Host != ""
}

Try / catch

client, err := webdav.NewReplicaClientFromURL(raw)
if err != nil && strings.Contains(err.Error(), "host required") {
    return fmt.Errorf("check webdav url in config, host part missing: %w", err)
}

Prevention

When it happens

Trigger: Configuring a replica URL like 'webdav:///dav' or 'webdav://:8080/path' (empty host), or programmatically passing a URL built without the host part.

Common situations: YAML config typo where the hostname was omitted or the URL was split across lines; templating/config expansion left the host variable empty (unset env var interpolated to nothing).

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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