kopia/kopia · error

TLS cert file already exists

Error message

TLS cert file already exists: %q

What it means

maybeGenerateTLS refuses to auto-generate a TLS certificate when the target cert file already exists, because generation would overwrite it. The check uses os.Stat success as evidence of existence. This protects an existing certificate from being silently replaced.

Solutions

  1. Remove/rename the existing cert file if regeneration is intended
  2. Drop --tls-generate-cert and let the server use the existing cert/key files
  3. Point --tls-cert-file/--tls-key-file at new paths

Example fix

// before
kopia server start --tls-generate-cert --tls-cert-file cert.pem --tls-key-file key.pem  # cert.pem exists
// after
rm cert.pem key.pem && kopia server start --tls-generate-cert --tls-cert-file cert.pem --tls-key-file key.pem
Defensive patterns

Strategy: validation

Validate before calling

if _, err := os.Stat(certFile); err == nil {
    return fmt.Errorf("refusing to generate: %s exists", certFile)
}

Prevention

When it happens

Trigger: Running `kopia server start --tls-generate-cert --tls-cert-file <path> --tls-key-file <path>` when <path> already exists on disk from a previous run.

Common situations: Re-running server start with the same cert path after an earlier generation; leftover files in a data directory; a config that pins a long-lived cert file while also requesting generation.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/a44258bc4b708d3c. Report an issue: GitHub.

Appendix: source

Thrown at cli/command_server_tls.go:90

		l.Close() //nolint:errcheck

		return errors.Wrap(err, "insecure server bind validation")
	}

	defer l.Close() //nolint:errcheck

	httpServer.Addr = l.Addr().String()

	return c.startServerWithOptionalTLSAndListener(ctx, httpServer, l)
}

func (c *commandServerStart) maybeGenerateTLS(ctx context.Context) error {
	if !c.serverStartTLSGenerateCert || c.serverStartTLSCertFile == "" || c.serverStartTLSKeyFile == "" {
		return nil
	}

	if _, err := os.Stat(c.serverStartTLSCertFile); err == nil {
		return errors.Errorf("TLS cert file already exists: %q", c.serverStartTLSCertFile)
	}

	if _, err := os.Stat(c.serverStartTLSKeyFile); err == nil {
		return errors.Errorf("TLS key file already exists: %q", c.serverStartTLSKeyFile)
	}

	cert, key, err := c.generateServerCertificate(ctx)
	if err != nil {
		return errors.Wrap(err, "unable to generate server cert")
	}

	fingerprint := sha256.Sum256(cert.Raw)
	fmt.Fprintf(c.out.stderr(), "SERVER CERT SHA256: %v\n", hex.EncodeToString(fingerprint[:])) //nolint:errcheck

	log(ctx).Infof("writing TLS certificate to %v", c.serverStartTLSCertFile)

	if err := tlsutil.WriteCertificateToFile(c.serverStartTLSCertFile, cert); err != nil {
		return errors.Wrap(err, "unable to write private key")

View on GitHub (pinned to 82495e54b5)