JuliusBrussee/caveman · error

bedrock Mantle endpoint is not enabled

Error message

bedrock Mantle endpoint is not enabled

What it means

The Bedrock Mantle endpoint (bedrock-mantle.<region>.api.aws, the Anthropic Messages wire on a separate AWS surface) is deployment-opt-in: its IAM service, model coverage, quotas, and stream wire differ from Bedrock Runtime. ResolveUpstreamURL refuses every /bedrock/anthropic/... request unless CAVE_BEDROCK_MANTLE_ENABLED is explicitly set to true.

Solutions

  1. Set CAVE_BEDROCK_MANTLE_ENABLED=true in the proxy's process environment and restart the proxy
  2. Confirm the variable is visible to the actual proxy process (e.g. systemctl show-environment, docker exec env) not just your shell
  3. If Mantle is not intended, switch the client to the Runtime route (/bedrock/model/<modelId>/invoke or converse) instead
  4. Check provider docs: Mantle is opt-in because model coverage and billing differ from Runtime

Example fix

# before (proxy env)
# CAVE_BEDROCK_MANTLE_ENABLED unset -> /bedrock/anthropic/v1/messages rejected
# after
CAVE_BEDROCK_MANTLE_ENABLED=true
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("CAVE_BEDROCK_MANTLE_ENABLED") != "true" && strings.HasPrefix(path, "/bedrock/anthropic/") {
	// enable the flag or reroute before sending
}

Try / catch

resp, err := client.Do(req)
if err != nil && strings.Contains(err.Error(), "Mantle endpoint is not enabled") {
	// set CAVE_BEDROCK_MANTLE_ENABLED=true and restart, or fall back to
	// POST /bedrock/model/<id>/invoke
}

Prevention

When it happens

Trigger: Any request whose path starts with /bedrock/anthropic/ (e.g. POST /bedrock/anthropic/v1/messages) while the CAVE_BEDROCK_MANTLE_ENABLED environment variable is unset or false at proxy start.

Common situations: A client configured for the Mantle/Anthropic-on-Mantle route but the operator never enabled the flag; the flag set in a shell but not in the proxy's service environment (systemd unit, container env); operator upgraded and forgot to re-apply the opt-in env var.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/6576f7aec728432c. Report an issue: GitHub.

Appendix: source

Thrown at proxy/providers/bedrock/routing.go:183

	switch kind {
	case endpointRuntime:
		if !RegionAllowed(region) {
			return nil, fmt.Errorf("bedrock region %q is not on the allowlist", region)
		}
		modelID, action := parseModelPath(req.URL.Path)
		if modelID == "" || action == "" {
			return nil, fmt.Errorf("bedrock request path %q does not name a model and action", req.URL.Path)
		}
		if !actionAllowed(action) {
			return nil, fmt.Errorf("bedrock action %q is not allowed", action)
		}
		if !modelAllowed(modelID) {
			return nil, fmt.Errorf("bedrock model %q is not on the allowlist", modelID)
		}
		base.Path = strings.TrimRight(base.Path, "/") + strings.TrimPrefix(req.URL.Path, "/bedrock")
	case endpointMantle:
		if !env.Bool("CAVE_BEDROCK_MANTLE_ENABLED", false) {
			return nil, fmt.Errorf("bedrock Mantle endpoint is not enabled")
		}
		if !MantleRegionAllowed(region) {
			return nil, fmt.Errorf("bedrock Mantle region %q is not on the allowlist", region)
		}
		if !mantleActionAllowed(req.URL.Path) {
			return nil, fmt.Errorf("bedrock Mantle path %q is not allowed", req.URL.Path)
		}
		base, err = resolveMantleBase(base, region)
		if err != nil {
			return nil, err
		}
		base.Path = strings.TrimRight(base.Path, "/") + strings.TrimPrefix(req.URL.Path, "/bedrock")
	default:
		return nil, fmt.Errorf("bedrock request path %q is not allowed", req.URL.Path)
	}
	base.RawQuery = req.URL.RawQuery

	if env.IsProduction() {

View on GitHub (pinned to 3ee70a1026)