JuliusBrussee/caveman · error

bedrock endpoint host

Error message

bedrock endpoint host %q does not match endpoint kind %q

What it means

In production, after building the upstream URL, ResolveUpstreamURL re-derives the endpoint kind from the resolved host (bedrock-runtime.*.amazonaws.com = runtime, bedrock-mantle.*.api.aws = mantle) and requires it to equal the kind implied by the request path. This invariant guarantees routing, signing region, and SSRF validation all target the same surface; a mismatch means the configured base URL or route pointed at the wrong Bedrock host kind.

Solutions

  1. Align the configured base URL with the request path kind: use https://bedrock-runtime.<region>.amazonaws.com for /bedrock/model/... and https://bedrock-mantle.<region>.api.aws for /bedrock/anthropic/...
  2. Leave route base_url empty to let the adapter derive the correct host from the region
  3. Verify bedrockHostKind can parse the host: exactly 4 DNS labels with bedrock-runtime[-fips] under amazonaws.com or bedrock-mantle under api.aws and an allowlisted region label
  4. Remove any custom base URL override that points a Runtime route at a Mantle host (or vice versa)

Example fix

// before (caveman.yaml route)
base_url: https://bedrock-mantle.us-east-1.api.aws  # Mantle host for a Runtime path
// after
base_url: https://bedrock-runtime.us-east-1.amazonaws.com
Defensive patterns

Strategy: validation

Validate before calling

func baseMatchesKind(baseURL, kind string) bool {
	host := strings.SplitN(strings.TrimPrefix(baseURL, "https://"), "/", 2)[0]
	isMantle := strings.HasPrefix(host, "bedrock-mantle.") && strings.HasSuffix(host, ".api.aws")
	isRuntime := strings.HasPrefix(host, "bedrock-runtime") && strings.HasSuffix(host, ".amazonaws.com")
	if kind == "mantle" { return isMantle }
	if kind == "runtime" { return isRuntime }
	return false
}
// verify route base_url against the path kind before configuring the route

Prevention

When it happens

Trigger: RouteContext.BaseURL (or the adapter's BaseURL) configured with a Mantle host (bedrock-mantle.<region>.api.aws) while serving a /bedrock/model/... Runtime request, or vice versa; a typo'd/custom base URL that bedrockHostKind cannot classify (ok=false also triggers this); a non-4-label hostname like bedrock-runtime.example.com failing kind detection.

Common situations: Operator set route base_url to the Mantle endpoint but clients call the Runtime path (or the reverse); copy-pasting a base URL from Mantle docs into a Runtime route config; self-hosted/test base URLs that pass locally but hit this check when CAVE_ENV indicates production; DNS/CNAME tricks mapping a Bedrock-shaped path to a non-Bedrock host.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

			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() {
		if err := providers.ValidateUpstreamEndpoint(ctx, base, ssrf.ManagedConfig()); err != nil {
			return nil, err
		}
		hostKind, _, ok := bedrockHostKind(base.Hostname())
		if !ok || hostKind != kind {
			return nil, fmt.Errorf("bedrock endpoint host %q does not match endpoint kind %q", base.Hostname(), kind)
		}
	}
	return base, nil
}

func endpointKindForPath(path string) string {
	switch {
	case strings.HasPrefix(path, "/bedrock/model/"):
		return endpointRuntime
	case strings.HasPrefix(path, "/bedrock/anthropic/"):
		return endpointMantle
	default:
		return ""
	}
}

func mantleActionAllowed(path string) bool {
	switch path {

View on GitHub (pinned to 3ee70a1026)