amir20/dozzle · error

failed to read certificates

Error message

failed to read certificates: %w

What it means

The `dozzle healthcheck` command, when an agent address file exists, loads TLS certificates via ReadCertificates (embedded + provided cert/key paths) before making an RPC request to the agent. If the cert files cannot be read or parsed, the error is wrapped as 'failed to read certificates'.

Solutions

  1. Verify the cert and key file paths passed to the command exist and are readable
  2. Re-run `make generate` (or recreate the container) to regenerate shared certs and mount them correctly
  3. Check file permissions so the dozzle process user can read both files
  4. Validate the files contain valid PEM certificates

Example fix

// before
docker run ... -v ./certs:/certs dozzle healthcheck --cert-file /wrong/cert.pem --key-file /wrong/key.pem
// after
docker run ... -v ./certs:/certs dozzle healthcheck --cert-file /certs/shared_cert.pem --key-file /certs/shared_key.pem
Defensive patterns

Strategy: validation

Validate before calling

for f in "$CERT" "$KEY"; do
  [ -r "$f" ] || { echo "missing/unreadable cert file: $f" >&2; exit 1; }
  openssl x509 -in "$CERT" -noout >/dev/null 2>&1 || { echo 'invalid PEM cert' >&2; exit 1; }
done

Prevention

When it happens

Trigger: Running `dozzle healthcheck` with --cert-file/--key-file paths that don't exist, are unreadable (permissions), or contain invalid PEM data; missing mounted certificates in the container.

Common situations: Docker deployments where shared_cert.pem/shared_key.pem are not mounted at the expected path; stale cert paths after volume changes; corrupted or empty cert files.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at internal/support/cli/health_command.go:25

	"net"
	"os"

	"github.com/amir20/dozzle/internal/healthcheck"
	"github.com/rs/zerolog/log"
)

type HealthcheckCmd struct{}

func (h *HealthcheckCmd) Run(args Args, embeddedCerts embed.FS) error {
	const agentAddrFile = "/tmp/dozzle-agent.addr"
	if data, err := os.ReadFile(agentAddrFile); err == nil {
		agentAddress := string(data)
		if host, port, err := net.SplitHostPort(agentAddress); err == nil && (host == "" || host == "::" || host == "0.0.0.0") {
			agentAddress = "127.0.0.1:" + port
		}
		certs, err := ReadCertificates(embeddedCerts, args.CertPath, args.KeyPath)
		if err != nil {
			return fmt.Errorf("failed to read certificates: %w", err)
		}
		ctx, cancel := context.WithTimeout(context.Background(), args.Timeout)
		defer cancel()
		log.Info().Str("address", agentAddress).Msg("Making RPC request to agent")
		return healthcheck.RPCRequest(ctx, agentAddress, certs)
	} else {
		log.Info().Str("address", args.Addr).Str("base", args.Base).Msg("Making HTTP request to server")
		return healthcheck.HttpRequest(args.Addr, args.Base)
	}
}

View on GitHub (pinned to d9463cbe21)