gofiber/fiber · error

tls: AutoCertManager cannot be combined with…

Error message

tls: AutoCertManager cannot be combined with CertFile/CertKeyFile

What it means

ErrAutoCertWithCertFile is returned by App.Listen (listen.go:226) when a ListenConfig supplies both an AutoCertManager and at least one of CertFile or CertKeyFile. These two TLS sources are mutually exclusive because autocert manages its certificates internally, so letting the caller also pin a static cert would produce ambiguous TLS behavior.

Solutions

  1. For autocert, omit CertFile and CertKeyFile: app.Listen(addr, fiber.ListenConfig{AutoCertManager: mgr}).
  2. For static certs, omit AutoCertManager: app.Listen(addr, fiber.ListenConfig{CertFile: cf, CertKeyFile: kf}).
  3. Centralize TLS configuration in one struct so the two sources are never both populated.

Example fix

// before
app.Listen(":443", fiber.ListenConfig{
    AutoCertManager: mgr,
    CertFile:        "fullchain.pem",
    CertKeyFile:     "privkey.pem",
})
// after
app.Listen(":443", fiber.ListenConfig{
    AutoCertManager: mgr,
})
Defensive patterns

Strategy: validation

Validate before calling

// Reject incompatible TLS configs before calling Listen.
func validateTLS(cfg fiber.ListenConfig) error {
    if cfg.AutoCertManager != nil && (cfg.CertFile != "" || cfg.CertKeyFile != "") {
        return fiber.ErrAutoCertWithCertFile
    }
    return nil
}

Try / catch

if err := app.Listen(":443", cfg); err != nil {
    if errors.Is(err, fiber.ErrAutoCertWithCertFile) {
        log.Fatal("choose either AutoCertManager OR CertFile/CertKeyFile, not both")
    }
    log.Fatal(err)
}

Prevention

When it happens

Trigger: Calling app.Listen(addr, fiber.ListenConfig{AutoCertManager: mgr, CertFile: "fullchain.pem", CertKeyFile: "privkey.pem"}). The switch in listen.go:225-227 sees both sources and returns the sentinel before configuring any TLS.

Common situations: Migrating from static certs to Let's Encrypt autocert and forgetting to clear the CertFile/CertKeyFile fields; copy-pasting a ListenConfig struct; combining staging and production TLS configs.

Understand the failure class

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/1fda7c882c41f821. Report an issue: GitHub.

Appendix: source

Thrown at error.go:24

	"github.com/gofiber/schema"
)

// Wrap and return this for unreachable code if panicking is undesirable (i.e., in a handler).
// Unexported because users will hopefully never need to see it.
var errUnreachable = errors.New("fiber: unreachable code, please create an issue at github.com/gofiber/fiber")

// General errors
var (
	ErrGracefulTimeout = errors.New("shutdown: graceful timeout has been reached, exiting")
	// ErrNotRunning indicates that a Shutdown method was called when the server was not running.
	ErrNotRunning = errors.New("shutdown: server is not running")
	// ErrHandlerExited is returned by App.Test if a handler panics or calls runtime.Goexit().
	ErrHandlerExited = errors.New("runtime.Goexit() called in handler or server panic")
	// ErrNoViewEngineConfigured indicates that a helper requiring a view engine was invoked without one configured.
	ErrNoViewEngineConfigured = errors.New("fiber: no view engine configured")
	// ErrAutoCertWithCertFile indicates AutoCertManager cannot be used with CertFile/CertKeyFile.
	ErrAutoCertWithCertFile = errors.New("tls: AutoCertManager cannot be combined with CertFile/CertKeyFile")
	// ErrRouteNotRepresentable indicates a route whose path no relative URL can
	// name, so Route.URL, GetRouteURL and Redirect().Route cannot compose one.
	// A path starting with two or more slashes is such a route: the URL that
	// would reach it opens an authority instead.
	ErrRouteNotRepresentable = errors.New("router: route path cannot be expressed as a relative URL")
)

// Fiber redirection errors
var (
	ErrRedirectBackNoFallback = NewError(StatusInternalServerError, "Referer not found, you have to enter fallback URL for redirection.")
)

// Range errors
var (
	// ErrRangeMalformed is returned for a syntactically invalid Range header,
	// which RFC 9110 Section 14.2 allows a server to reject; it carries a
	// 400 Bad Request status so propagating it does not surface as a 500.
	ErrRangeMalformed = NewError(StatusBadRequest, "range: malformed range header string")

View on GitHub (pinned to a105acad6c)