gohugoio/hugo · error

failed to verify certificate: %v

Error message

failed to verify certificate: %v

What it means

The cached certificate parsed cleanly, but chain verification against the mkcert root CA failed for the requested hostname (`cert.Verify` with `DNSName` and the mkcert root pool). Hugo uses this check to decide whether a cached cert is still usable; failure typically means expiry, hostname mismatch, or a cert signed by a different (e.g. regenerated) mkcert root.

Source

Thrown at commands/server.go:747

		return fmt.Errorf("failed to parse root certificate")
	}

	block, _ := pem.Decode(certPEM)
	if block == nil {
		return fmt.Errorf("failed to parse certificate PEM")
	}
	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		return fmt.Errorf("failed to parse certificate: %v", err.Error())
	}

	opts := x509.VerifyOptions{
		DNSName: name,
		Roots:   roots,
	}

	if _, err := cert.Verify(opts); err != nil {
		return fmt.Errorf("failed to verify certificate: %v", err.Error())
	}

	return nil
}

func (c *serverCommand) createServerPorts(cd *simplecobra.Commandeer) error {
	flags := cd.CobraCommand.Flags()
	var cerr error
	c.withConf(func(conf *commonConfig) {
		isMultihost := conf.configs.IsMultihost
		c.serverPorts = make([]serverPortListener, 1)
		if isMultihost {
			if !c.serverAppend {
				cerr = errors.New("--appendPort=false not supported when in multihost mode")
				return
			}
			c.serverPorts = make([]serverPortListener, len(conf.configs.Languages))
		}

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. Delete `<hugo cacheDir>/_mkcerts/` so Hugo mints a fresh cert for the current hostname against the current mkcert root.
  2. If you changed the site's baseURL hostname, expect a new cert to be generated — clear the stale one for the old name.
  3. Re-run `mkcert -install` if the root CA was rotated, then regenerate.
  4. Check expiry: `openssl x509 -in <host>.pem -noout -dates -ext subjectAltName`.
Defensive patterns

Strategy: validation

Validate before calling

if _, err := cert.Verify(x509.VerifyOptions{Roots: pool, DNSName: host}); err != nil {
    return fmt.Errorf("cert won't verify against provided CA: %w", err)
}

Try / catch

cert, err := server.Serve()
if err != nil && strings.Contains(err.Error(), "failed to verify certificate") {
    log.Fatal("TLS cert not signed by the given CA or expired — regenerate with mkcert/hugo server trust")
}

Prevention

When it happens

Trigger: `hugo server --tlsAuto` where the cached cert is expired, its SANs don't cover the hostname derived from `--baseURL` (default `localhost`), or the mkcert root CA was reinstalled/rotated since the cert was minted so the chain no longer terminates at the current `rootCA.pem`.

Common situations: Changing `--baseURL`/config baseURL to a new hostname while an old `localhost` cert is cached; mkcert reinstalled after an OS refresh, invalidating old leaf certs; long-lived dev machines where the cached cert expired.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/045aabd313b0ca87.json. Report an issue: GitHub ↗.