JuliusBrussee/caveman · error

bedrock configured endpoint kind %q does not allow request k

Error message

bedrock configured endpoint kind %q does not allow request kind %q

What it means

Bedrock classifies each request path as runtime or mantle endpoint kind. If a route was explicitly configured with an EndpointKind and the incoming request's path resolves to a different kind, the adapter refuses to forward — a mantle-configured route must not silently serve runtime-shaped requests (their IAM services, quotas, and wire behavior differ). Both surfaces still report provider=bedrock in telemetry; this is a per-route safety check.

Source

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

// quotas, features, stream wire, and AWS invocation-logging support differ from
// Runtime. Both surfaces remain provider=bedrock in telemetry.
func (a Adapter) ResolveUpstreamURL(ctx context.Context, req *http.Request, route providers.RouteContext) (*url.URL, error) {
	baseURL := a.BaseURL
	if route.BaseURL != "" {
		baseURL = route.BaseURL
	}
	base, err := url.Parse(baseURL)
	if err != nil {
		return nil, fmt.Errorf("bedrock base url invalid: %w", err)
	}
	region, err := resolveRegion(req, base)
	if err != nil {
		return nil, err
	}

	kind := endpointKindForPath(req.URL.Path)
	if configuredKind := strings.ToLower(strings.TrimSpace(route.EndpointKind)); configuredKind != "" && configuredKind != kind {
		return nil, fmt.Errorf("bedrock configured endpoint kind %q does not allow request kind %q", configuredKind, kind)
	}
	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:

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Align the client's request path with the configured endpoint kind: use mantle-shaped paths only on mantle routes, runtime-shaped paths only on runtime routes.
  2. If the route should serve both, leave endpoint_kind unset — an empty configured kind allows either.
  3. Check for accidental whitespace/casing in the configured kind; ' Mantle ' trims to 'mantle' but 'mantel' will never match and effectively forces the mismatch branch.

Example fix

# before (caveman.yaml)
routes:
  bedrock-main:
    provider: bedrock
    endpoint_kind: mantle
# client still calls: POST /bedrock/model/anthropic.claude.../invoke  (runtime path)

# after
routes:
  bedrock-main:
    provider: bedrock
    endpoint_kind: runtime   # matches the client's runtime-shaped path
Defensive patterns

Strategy: validation

Validate before calling

// Mirror the adapter's kind classification before sending.
func requestKind(path string) string {
    if strings.Contains(path, "/bedrock/") && !strings.Contains(path, "anthropic/") {
        return "runtime" // adjust to your routing table's shape
    }
    return "mantle"
}
configured := strings.ToLower(strings.TrimSpace(route.EndpointKind))
if configured != "" && configured != requestKind(req.URL.Path) {
    return fmt.Errorf("route kind %q does not match request path %q", configured, req.URL.Path)
}

Type guard

func routeKindMatches(configured, path string) bool {
    c := strings.ToLower(strings.TrimSpace(configured))
    return c == "" || c == requestKind(path)
}

Try / catch

if _, err := adapter.ResolveUpstreamURL(ctx, req, route); err != nil {
    if strings.Contains(err.Error(), "does not allow request kind") {
        http.Error(w, "request path does not match the route's configured bedrock endpoint kind", http.StatusBadRequest)
        return
    }
    http.Error(w, err.Error(), http.StatusBadRequest)
}

Prevention

When it happens

Trigger: Configuring a route with endpoint_kind: mantle (or runtime) and then sending a request whose path matches the other kind — e.g. a mantle route receiving /bedrock/anthropic/v1/messages or a runtime route receiving a mantle-style path.

Common situations: Copy-pasting a route block from a mantle deployment and pointing existing runtime clients at it; enabling mantle opt-in then forgetting to update client base paths; case/whitespace differences are tolerated (the check lower-cases and trims) but kind mismatch is not.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/805ed3ae95796981. Report an issue: GitHub.