vxcontrol/pentagi · error

bearer scheme must be used

Error message

bearer scheme must be used

What it means

tryProtoTokenAuthentication in backend/pkg/server/auth/auth_middleware.go rejects an Authorization header that is present but does not start with the exact prefix "Bearer ". The middleware only accepts bearer-token authentication for programmatic API access; any other auth scheme (Basic, raw token, lowercase "bearer") is skipped so other auth paths can be tried, and this error records why. It is a request-shape error, not a token-validity error.

Source

Thrown at backend/pkg/server/auth/auth_middleware.go:203

	c.Set("uname", uname.(string))

	if slices.Contains(prms, PrivilegeAutomation) {
		c.Set("cpt", "automation")
	}

	return authResultOk, nil
}

const PrivilegeAutomation = "pentagi.automation"

func (p *AuthMiddleware) tryProtoTokenAuthentication(c *gin.Context) (authResult, error) {
	authHeader := c.Request.Header.Get("Authorization")
	if authHeader == "" {
		return authResultSkip, errors.New("token required")
	}

	if !strings.HasPrefix(authHeader, "Bearer ") {
		return authResultSkip, errors.New("bearer scheme must be used")
	}
	token := authHeader[7:]
	if token == "" {
		return authResultSkip, errors.New("token can't be empty")
	}

	// skip validation if using default salt (for backward compatibility)
	if p.globalSalt == "" || p.globalSalt == "salt" {
		return authResultSkip, errors.New("token validation disabled with default salt")
	}

	// try to validate as API token first (new format with JWT signing key)
	apiClaims, apiErr := ValidateAPIToken(token, p.globalSalt)
	if apiErr != nil {
		return authResultFail, errors.New("token is invalid")
	}

	// check token status and get privileges through cache

View on GitHub (pinned to ea665308ba)

Solutions

  1. Set the header exactly to `Authorization: Bearer <api-token>` (capital B, one space).
  2. If using curl, use `-H "Authorization: Bearer $TOKEN"` instead of `-u` or a bare token header.
  3. If your client library has an auth helper (e.g. axios AuthInterceptor with token type 'Bearer'), configure it rather than writing the header manually.
  4. If you intended cookie/session auth, remove the Authorization header so the middleware falls through to session authentication.

Example fix

// before
req.Header.Set("Authorization", apiKey)

// after
req.Header.Set("Authorization", "Bearer "+apiKey)
Defensive patterns

Strategy: validation

Validate before calling

const auth = headers["Authorization"];
if (auth !== undefined && !auth.startsWith("Bearer ")) {
  throw new Error("Authorization header must use the Bearer scheme");
}

Type guard

function isBearerHeader(v: string | undefined): v is string {
  return typeof v === "string" && v.startsWith("Bearer ");
}

Try / catch

try {
  const res = await api.call();
} catch (e) {
  if (is401(e) && /bearer scheme/i.test(e.message)) {
    fixAuthorizationHeader();
  }
  throw e;
}

Prevention

When it happens

Trigger: Sending an Authorization header whose value does not begin with "Bearer " (case-sensitive, with a single space), e.g. `Authorization: Basic ...`, `Authorization: bearer abc123`, or `Authorization: <raw-token>` with no scheme at all, on an endpoint guarded by this middleware.

Common situations: Copy-pasting a token without the scheme; HTTP clients that auto-attach Basic auth; hand-rolled curl calls omitting the word Bearer; proxy or SDK that lowercases the scheme; using a session cookie flow expectation against the token endpoint.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/c1085e2517d3ff27. Report an issue: GitHub.