JuliusBrussee/caveman · error

bedrock configured endpoint kind

Error message

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

What it means

A route can pin an endpoint kind ("runtime" for /bedrock/model/... paths, "mantle" for /bedrock/anthropic/... paths) via route.EndpointKind. When the configured kind does not match the kind derived from the request path, the request is rejected so a route can never send traffic to an endpoint type it was not configured for.

Solutions

  1. Update the route's endpoint_kind to match the request path family ("runtime" for /bedrock/model/..., "mantle" for /bedrock/anthropic/...).
  2. Send the request to the path family the route is pinned to.
  3. If both kinds are needed, create two routes with separate endpoint_kind values.

Example fix

// before (caveman.yaml)
endpoint_kind: "mantle"
// request: POST /bedrock/model/anthropic.claude-3-5-sonnet/invoke
// after
endpoint_kind: "runtime"
Defensive patterns

Strategy: validation

Validate before calling

func kindMatches(path, configuredKind string) bool {
	configuredKind = strings.ToLower(strings.TrimSpace(configuredKind))
	if configuredKind == "" {
		return true
	}
	switch {
	case strings.HasPrefix(path, "/bedrock/model/"):
		return configuredKind == "runtime"
	case strings.HasPrefix(path, "/bedrock/anthropic/"):
		return configuredKind == "mantle"
	}
	return false
}

Prevention

When it happens

Trigger: A route configured with endpoint kind "mantle" receiving a /bedrock/model/{modelId}/{action} request, or a route configured with "runtime" receiving a /bedrock/anthropic/v1/messages request.

Common situations: Operator switched a route between Bedrock Runtime and Mantle without updating endpoint_kind; a client SDK sends the wrong path family for the route; case/whitespace mismatches in the configured kind are tolerated (trimmed/lowercased), so this is a genuine kind mismatch.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: 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 3ee70a1026)