gastownhall/beads · error

ExternalDoltConfig: TLSCert

Error message

ExternalDoltConfig: TLSCert %q is not absolute

What it means

ExternalDoltConfig.Validate requires TLSCert to be an absolute path when set. Client certificate files are read from disk during TLSClientConfig, and a relative path would depend on the process working directory, which is not guaranteed. This check runs at configuration validation time, before any connection is attempted.

Solutions

  1. Replace the TLSCert value with an absolute path, e.g. "/etc/beads/tls/client.pem".
  2. Expand "~/" and environment variables before writing them into the config.
  3. If mutual TLS is not needed, remove TLSCert (and TLSKey) entirely.

Example fix

// before
tlsCert: "~/certs/client.pem"
// after
tlsCert: "/home/alice/certs/client.pem"
Defensive patterns

Strategy: validation

Validate before calling

func validTLSCert(cfg configfile.ExternalDoltConfig) error {
    if cfg.TLSCert != "" && !filepath.IsAbs(cfg.TLSCert) {
        return fmt.Errorf("TLSCert must be absolute: %q", cfg.TLSCert)
    }
    return nil
}

Prevention

When it happens

Trigger: Calling Validate (via NewExternalDoltServer, NewExternalDoltServerUOWProvider, or buildProxiedServerClientInfo) with TLSCert set to a relative path like "certs/client.pem" or an unexpanded "~/certs/client.pem" (tilde is not absolute in Go).

Common situations: Config written with "~/..." paths assuming shell-style expansion; config files shared across machines with different cert locations; running the tool from a directory different from where the config was authored.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/b18419e92ecd63c3. Report an issue: GitHub.

Appendix: source

Thrown at internal/configfile/external_dolt_config.go:71

	}

	if hasHost && (c.Port < 1 || c.Port > 65535) {
		return fmt.Errorf("ExternalDoltConfig: Port %d out of range [1, 65535]", c.Port)
	}

	if hasSocket && !filepath.IsAbs(c.Socket) {
		return fmt.Errorf("ExternalDoltConfig: Socket %q is not absolute", c.Socket)
	}

	switch {
	case c.TLSCert != "" && c.TLSKey == "":
		return errors.New("ExternalDoltConfig: TLSCert set without TLSKey")
	case c.TLSCert == "" && c.TLSKey != "":
		return errors.New("ExternalDoltConfig: TLSKey set without TLSCert")
	}

	if c.TLSCert != "" && !filepath.IsAbs(c.TLSCert) {
		return fmt.Errorf("ExternalDoltConfig: TLSCert %q is not absolute", c.TLSCert)
	}
	if c.TLSKey != "" && !filepath.IsAbs(c.TLSKey) {
		return fmt.Errorf("ExternalDoltConfig: TLSKey %q is not absolute", c.TLSKey)
	}
	if c.TLSCACert != "" && !filepath.IsAbs(c.TLSCACert) {
		return fmt.Errorf("ExternalDoltConfig: TLSCACert %q is not absolute", c.TLSCACert)
	}

	if !c.TLSRequired {
		switch {
		case c.TLSCACert != "":
			return errors.New("ExternalDoltConfig: TLSCACert set without TLSRequired")
		case c.TLSCert != "" || c.TLSKey != "":
			return errors.New("ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired")
		case c.TLSServerName != "":
			return errors.New("ExternalDoltConfig: TLSServerName set without TLSRequired")
		case c.TLSSkipVerify:
			return errors.New("ExternalDoltConfig: TLSSkipVerify set without TLSRequired")

View on GitHub (pinned to 71377f2769)