labstack/echo · error

at least one AllowOrigins is required or UnsafeAllowOriginFu

Error message

at least one AllowOrigins is required or UnsafeAllowOriginFunc must be provided

What it means

Returned by CORSConfig.ToMiddleware when both AllowOrigins is empty and UnsafeAllowOriginFunc is nil. CORS requires at least one allowed origin (or a custom validator) to populate the Access-Control-Allow-Origin header; with neither, the middleware cannot decide whom to trust. Surfaced as a panic via CORSWithConfig / CORS().

Source

Thrown at middleware/cors.go:174

	hasCustomAllowMethods := true
	if len(config.AllowMethods) == 0 {
		hasCustomAllowMethods = false
		config.AllowMethods = []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete}
	}

	allowMethods := strings.Join(config.AllowMethods, ",")
	allowHeaders := strings.Join(config.AllowHeaders, ",")
	exposeHeaders := strings.Join(config.ExposeHeaders, ",")

	maxAge := "0"
	if config.MaxAge > 0 {
		maxAge = strconv.Itoa(config.MaxAge)
	}

	allowOriginFunc := config.UnsafeAllowOriginFunc
	if config.UnsafeAllowOriginFunc == nil {
		if len(config.AllowOrigins) == 0 {
			return nil, errors.New("at least one AllowOrigins is required or UnsafeAllowOriginFunc must be provided")
		}
		allowOriginFunc = config.defaultAllowOriginFunc
		for _, origin := range config.AllowOrigins {
			if origin == "*" {
				if config.AllowCredentials {
					return nil, fmt.Errorf("* as allowed origin and AllowCredentials=true is insecure and not allowed. Use custom UnsafeAllowOriginFunc")
				}
				allowOriginFunc = config.starAllowOriginFunc
				break
			}
			if err := validateOrigin(origin, "allow origin"); err != nil {
				return nil, err
			}
		}
		config.AllowOrigins = append([]string(nil), config.AllowOrigins...)
	}

	return func(next echo.HandlerFunc) echo.HandlerFunc {

View on GitHub (pinned to 05489dc173)

Solutions

  1. Pass at least one origin: CORS("https://app.example.com") or set AllowOrigins in the config.
  2. If origins must be computed dynamically, set UnsafeAllowOriginFunc instead (it overrides AllowOrigins).
  3. When loading origins from config/env, fail fast at boot if the resulting slice is empty rather than passing it to the middleware.
  4. Use config.ToMiddleware() to receive the error instead of a panic during wiring.

Example fix

// before
m := middleware.CORSWithConfig(middleware.CORSConfig{
    AllowMethods: []string{http.MethodGet, http.MethodPost},
})
// after
m := middleware.CORSWithConfig(middleware.CORSConfig{
    AllowOrigins: []string{"https://app.example.com"},
    AllowMethods: []string{http.MethodGet, http.MethodPost},
})
Defensive patterns

Strategy: validation

Validate before calling

func corsMiddleware(origins []string) (echo.MiddlewareFunc, error) {
    cfg := middleware.CORSConfig{AllowOrigins: origins}
    if len(cfg.AllowOrigins) == 0 && cfg.UnsafeAllowOriginFunc == nil {
        return nil, errors.New("CORS requires at least one AllowOrigins entry or UnsafeAllowOriginFunc")
    }
    return cfg.ToMiddleware()
}

Prevention

When it happens

Trigger: Calling CORSWithConfig(CORSConfig{}) with no AllowOrigins and no UnsafeAllowOriginFunc, or calling CORS() with zero variadic arguments (allowOrigins...string expands to nil).

Common situations: Developer switches from CORS("https://app.example.com") to CORSWithConfig to set AllowMethods/AllowHeaders and forgets to carry AllowOrigins over; or an empty env var feeds the origin list producing an empty slice.

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/5deceee6621d56e4.json. Report an issue: GitHub.