slackhq/nebula · error

unable to read crt: %w

Error message

unable to read crt: %w

What it means

After the CA pool is built, verify reads the certificate to be checked via readInput('crt', certPath). Any failure reading that input (missing file, unreadable, stdin conflict) is wrapped as 'unable to read crt' and verification aborts.

Source

Thrown at cmd/nebula-cert/verify.go:63

		"crt", *vf.certPath,
	); err != nil {
		return err
	}

	caReader, err := openInput("ca", *vf.caPath, &claims)
	if err != nil {
		return fmt.Errorf("error while reading ca: %w", err)
	}
	defer caReader.Close()

	caPool, err := cert.NewCAPoolFromPEMReader(caReader)
	if err != nil && !errors.Is(err, cert.ErrExpired) {
		return fmt.Errorf("error while adding ca cert to pool: %w", err)
	}

	rawCert, err := readInput("crt", *vf.certPath, &claims)
	if err != nil {
		return fmt.Errorf("unable to read crt: %w", err)
	}
	var errs []error
	for {
		if len(rawCert) == 0 {
			break
		}
		c, extra, err := cert.UnmarshalCertificateFromPEM(rawCert)
		if err != nil {
			return fmt.Errorf("error while parsing crt: %w", err)
		}
		rawCert = extra
		_, err = caPool.VerifyCertificate(time.Now(), c)
		if err != nil {
			switch {
			case errors.Is(err, cert.ErrCaNotFound):
				errs = append(errs, fmt.Errorf("error while verifying certificate v%d %s with issuer %s: %w", c.Version(), c.Name(), c.Issuer(), err))
			default:
				errs = append(errs, fmt.Errorf("error while verifying certificate %+v: %w", c, err))

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Verify the -crt path exists and is readable
  2. Use an absolute path or cd to the directory containing the cert
  3. Check file permissions
  4. Ensure only one input flag uses '-' if piping via stdin

Example fix

// before
./nebula-cert verify -ca ca.crt -crt host.crts   # typo
// after
./nebula-cert verify -ca ca.crt -crt host.crt
Defensive patterns

Strategy: validation

Validate before calling

import "os"
func checkReadable(path string) error {
    if path == "-" { return nil }
    f, err := os.Open(path)
    if err != nil { return err }
    return f.Close()
}
// err := checkReadable(crtPath) before invoking verify

Try / catch

out, err := exec.Command("nebula-cert", "verify", args...).CombinedOutput()
if err != nil && strings.Contains(string(out), "unable to read crt") {
    log.Printf("cert unreadable: %s", out)
}

Prevention

When it happens

Trigger: readInput returns an error for the -crt flag: file absent, no read permission, path is a directory, or stdin conflict when -crt is '-'.

Common situations: Wrong path or filename for the host certificate; cert not yet copied to the machine; running from wrong cwd; '-' used for both -ca and -crt.

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 slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/59fc8c8da7a3f078. Report an issue: GitHub.