gofiber/fiber · critical
failed to append certificate
Error message
failed to append certificate
What it means
Wraps the failure returned by tls.Config.RootCAs.AppendCertsFromPEM inside Client.SetRootCertificate (client/client.go:336) and SetRootCertificateFromString (client/client.go:351). AppendCertsFromPEM returns false when the PEM bytes contain no parseable certificate blocks; Fiber turns that into a logger.Panicf, terminating the program because client configuration is unrecoverable.
Solutions
- Verify the file is PEM-encoded: it must have '-----BEGIN CERTIFICATE-----' / '-----END CERTIFICATE-----' blocks. Convert DER with: openssl x509 -inform DER -in cert.der -out cert.pem -outform PEM.
- Inspect the file before passing it; ensure at least one CERTIFICATE block is present.
- Load and AppendCertsFromPEM in your own code first to get a real error rather than the panic, then assign tls.Config directly.
- If you must keep the panic behavior, gate the call behind a build/runtime check so misconfiguration surfaces at startup, not mid-request.
Example fix
// before
client.SetRootCertificate("/etc/secrets/ca.der") // ErrFailedToAppendCert panic
// after
// convert once: openssl x509 -inform DER -in ca.der -out ca.pem -outform PEM
client.SetRootCertificate("/etc/secrets/ca.pem") Defensive patterns
Strategy: validation
Validate before calling
// Validate the PEM in your own code to get a real error before the panic
func mustAppendCAs(pool *x509.CertPool, pem []byte) error {
if !pool.AppendCertsFromPEM(pem) {
return errors.New("PEM contained no parseable certificate")
}
return nil
}
// call this before client.SetRootCertificateFromString(string(pem)) Type guard
func looksLikePEMCert(pem []byte) bool {
return bytes.Contains(pem, []byte("-----BEGIN CERTIFICATE-----")) &&
bytes.Contains(pem, []byte("-----END CERTIFICATE-----"))
} Try / catch
// SetRootCertificate panics, so wrap setup in recover if you want graceful failure:
func safeSetRootCert(c *fiber.Client, path string) (err error) {
defer func() {
if r := recover(); r != nil { err = fmt.Errorf("%v", r) }
}()
c.SetRootCertificate(path)
return nil
} Prevention
- Always provide PEM-encoded CA bundles, never DER.
- Inspect the file with openssl x509 -in ca.pem -noout before pointing the client at it.
- Gate TLS setup at program start so a misconfiguration fails fast, not mid-request.
When it happens
Trigger: Calling client.SetRootCertificate(path) where the file is not valid PEM, contains only a private key, has a corrupted BEGIN/END block, or is empty; calling SetRootCertificateFromString(pem) with the contents of a CSR, a DER blob, or a typo-pasted bundle.
Common situations: Pointing SetRootCertificate at a certificate in DER instead of PEM format; passing a fullchain that includes non-certificate sections; copy/paste truncating the END line; reading a key file by mistake.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- client cannot be nil
- client: HTTPS to HTTP redirect blocked
- client panic
- failed to parse client CA certificate from
- tls: cannot load TLS key pair from certFile=
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/e6d4eba280f604d2.
Report an issue: GitHub.
Appendix: source
Thrown at client/client.go:34
"io"
"os"
"path/filepath"
"slices"
"sync"
"sync/atomic"
"time"
"github.com/fxamacker/cbor/v2"
"github.com/gofiber/fiber/v3/log"
"github.com/gofiber/utils/v2"
"github.com/valyala/fasthttp"
"github.com/valyala/fasthttp/fasthttpproxy"
"golang.org/x/net/http/httpproxy"
)
var ErrFailedToAppendCert = errors.New("failed to append certificate")
// Client provides Fiber's high-level HTTP API while delegating transport work
// to fasthttp.Client, fasthttp.HostClient, or fasthttp.LBClient implementations.
//
// Settings configured on the client are shared across every request and may be
// overridden per request when needed.
// Client is safe for concurrent request execution after configuration is
// complete. Concurrent configuration changes require external synchronization.
type Client struct {
logger log.CommonLogger
transport httpClientTransport
header *Header
params *QueryParam
cookies *Cookie
path *PathParam
jsonMarshal utils.JSONMarshalView on GitHub (pinned to a105acad6c)