amir20/dozzle · error

invalid scheme

Error message

invalid scheme: %s

What it means

NewRemoteClient validates that the remote host URL uses the 'tcp' scheme before constructing a Docker API client. Docker's remote API client only speaks tcp:// (with tls:// handled via options). Any other scheme in container.Host.URL means the host entry is malformed for remote connections.

Solutions

  1. Change the remote host URL scheme to tcp, e.g. tcp://192.168.1.10:2375
  2. If you intended a local socket, do not add it as a remote host; local unix sockets are handled by the default client
  3. Validate host entries before passing them to CreateMultiHostService

Example fix

// before
hosts := []container.Host{{Name: "node1", URL: mustParse("unix:///var/run/docker.sock")}}
svc, err := docker.NewRemoteClient(host)
// after
hosts := []container.Host{{Name: "node1", URL: mustParse("tcp://192.168.1.10:2375")}}
svc, err := docker.NewRemoteClient(host)
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(hostURL)
if err != nil || u.Scheme != "tcp" {
    return fmt.Errorf("remote host must use tcp:// scheme, got %q", hostURL)
}

Prevention

When it happens

Trigger: Calling NewRemoteClient (via CreateMultiHostService) with a container.Host whose URL.Scheme is not "tcp", e.g. a host configured as "unix:///var/run/docker.sock", "http://host:2375", or a typo like "tcpp://host:2375".

Common situations: Users put a unix socket path in a remote host definition in dozzle config/env, copy an HTTP URL from browser tooling, or misconfigure DOZZLE_REMOTE_HOST entries with the wrong scheme prefix.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/38e60d38d5543c0e. Report an issue: GitHub.

Appendix: source

Thrown at internal/docker/client.go:119

	}
	info := infoResult.Info

	host := container.Host{
		Name:     info.Name,
		Endpoint: "local",
		Type:     "local",
	}

	if hostname != "" {
		host.Name = hostname
	}

	return NewClient(cli, host), nil
}

func NewRemoteClient(host container.Host) (*DockerClient, error) {
	if host.URL.Scheme != "tcp" {
		return nil, fmt.Errorf("invalid scheme: %s", host.URL.Scheme)
	}

	opts := []client.Opt{
		client.WithHost(host.URL.String()),
	}

	if host.ValidCerts {
		log.Debug().Str("caCertPath", host.CACertPath).Str("certPath", host.CertPath).Str("keyPath", host.KeyPath).Msg("Using TLS for remote client")
		opts = append(opts, client.WithTLSClientConfig(host.CACertPath, host.CertPath, host.KeyPath))
	} else {
		log.Debug().Msg("Not using TLS for remote client")
	}

	opts = append(opts, client.WithUserAgent("Docker-Client/Dozzle"))

	cli, err := client.New(opts...)

	if err != nil {

View on GitHub (pinned to d9463cbe21)