ory/hydra · error

can not serve request over insecure http

Error message

can not serve request over insecure http

What it means

The TLS termination middleware rejects requests that arrive over plain HTTP when no trusted termination networks are configured. Because TLS termination is not enabled, the proxy cannot verify that the connection was secured upstream, so it responds 502 Bad Gateway with this message and logs 'TLS termination is not enabled'.

Source

Thrown at oryx/tlsx/termination.go:50

		_, network, err := net.ParseCIDR(rn)
		if err != nil {
			return nil, errors.WithStack(err)
		}
		networks = append(networks, network)
	}

	return negroni.HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
		if r.TLS != nil ||
			r.URL.Path == healthx.AliveCheckPath ||
			r.URL.Path == healthx.ReadyCheckPath ||
			r.URL.Path == prometheusx.MetricsPrometheusPath {
			next(rw, r)
			return
		}

		if len(networks) == 0 {
			d.Logger().WithRequest(r).WithError(errors.New("TLS termination is not enabled")).Error("Could not serve http connection")
			d.Writer().WriteErrorCode(rw, r, http.StatusBadGateway, errors.New("can not serve request over insecure http"))
			return
		}

		if err := matchesRange(r, networks); err != nil {
			d.Logger().WithRequest(r).WithError(err).Warnln("Could not serve http connection")
			d.Writer().WriteErrorCode(rw, r, http.StatusBadGateway, errors.New("can not serve request over insecure http"))
			return
		}

		proto := r.Header.Get("X-Forwarded-Proto")
		if proto == "" {
			d.Logger().WithRequest(r).WithError(errors.New("X-Forwarded-Proto header is missing")).Error("Could not serve http connection")
			d.Writer().WriteErrorCode(rw, r, http.StatusBadGateway, errors.New("can not serve request over insecure http"))
			return
		} else if proto != "https" {
			d.Logger().WithRequest(r).WithError(errors.New("X-Forwarded-Proto header is missing")).Error("Could not serve http connection")
			d.Writer().WriteErrorCode(rw, r, http.StatusBadGateway, errors.Errorf("expected X-Forwarded-Proto header to be https but got: %s", proto))
			return

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Configure the trusted TLS-termination proxy networks (CIDR ranges) so the middleware accepts forwarded connections
  2. If TLS termination is not used, serve over HTTPS directly or skip installing the termination middleware
  3. Ensure the proxy's source IP actually falls within the configured networks
  4. For local development, run with HTTPS or disable the middleware

Example fix

// before
// termination middleware enabled, no networks configured -> 502
// after
err := d.TerminationMiddleware([]string{"10.0.0.0/8"})(next).ServeHTTP(rw, r) // trust internal LB range
Defensive patterns

Strategy: try-catch

Validate before calling

if !tlsTerminationEnabled && requestIsHTTP {
	// do not install the termination middleware, or configure networks first
}

Type guard

func isTerminationRejection(status int) bool {
	return status == http.StatusBadGateway // middleware responds 502 with "can not serve request over insecure http"
}

Try / catch

// client side
resp, err := http.Get(url)
if err == nil && resp.StatusCode == http.StatusBadGateway {
	body, _ := io.ReadAll(resp.Body)
	if strings.Contains(string(body), "insecure http") {
		// switch to HTTPS or route via the trusted TLS-terminating proxy
	}
}

Prevention

When it happens

Trigger: An HTTP request reaches the middleware while the terminator allowlist is empty (len(networks) == 0) — i.e. the middleware was installed but no trusted CIDR ranges for TLS-terminating proxies were configured.

Common situations: Deploying behind a load balancer (AWS ELB, Cloudflare, nginx) that terminates TLS but forgetting to configure the proxy's IP ranges; running the service on http:// during local development while the middleware is enabled; misread environment/config causing the networks list to load empty.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/07fb87996b8db89d. Report an issue: GitHub.