Reason codes

The string reason_code vocabulary and when each is emitted.

reason_code is a string, not a proto enum — new codes can be added without breaking old clients. Clients must treat any unrecognized code as the no-hint default (fail open, round-robin).

LookupRoute / LookupPDRoute

CodeWhen emitted
PREFIX_MATCHA replica holds the exact prefix or a leading block-run; the ranker returns a non-empty list; at least one replica clears minimumMatchedTokens (default 64) and the top score clears routingFloorScore (default 0.1).
NO_HINTThe fail-open default: a novel prefix with no affinity fallback, an empty/unspecified key, cold start (globally empty index), a request gated below minimumPrefixTokens, a sub-floor matched-tokens/score result (with affinity disabled), or a disabled index.
TENANT_HOTPrefix miss, strategy.enableTenantHot ≠ false, and a warm replica exists (recent stats, hit_rate above the floor, serving the requested scheme). matched_tokens = 0.
AFFINITY_HINTWould-be NO_HINT, affinityRouting: Enabled, a usable fingerprint, and ≥1 serving replica. A single stable replica; score / matched_tokens / estimated_cache_hit_prob are all 0.
POLICY_REQUIRES_CHAINstrategy.requireChain: true and the request has no valid block-hash chain. Returned before touching the index.
TIMEOUTThe lookup deadline expired (context deadline, or lookupTimeoutMs elapsed). Fail-open. Clients may also synthesize this locally.
UNKNOWN_TENANTMiss, and the (non-empty) tenant_id has zero entries anywhere (index not globally empty). A contract-key mismatch — likely a misconfigured client.
UNKNOWN_MODELMiss, tenant known, but (tenant, model) has zero entries.
UNKNOWN_HASH_SCHEMEMiss, (tenant, model) has entries, but none under the request’s hash_scheme.

LookupPDRoute is a stub today and always returns no hint.

Diagnosing UNKNOWN_*

The three UNKNOWN_* codes distinguish a genuinely novel prefix from a client sending wrong contract keys (the common silent misconfiguration: mismatched hash_scheme or tenant_id between the producer and the gateway). Treat them like an HTTP 4xx — log, emit a metric, fail open, and do not retry. The mismatch is in your client configuration, not the server. See LookupRoute & ranking.

The ranking knobs behind these codes

KnobWhereDefaultOff
minimumMatchedTokensCachePolicy640
routingFloorScoreCachePolicy"0.1""0"
strategy.enableChainMatchingCachePolicytruefalse
strategy.requireChainCachePolicyfalse(n/a)
strategy.enableTenantHotCachePolicytruefalse
affinityRoutingCachePolicyEnabledDisabled
PressureWeightserver RankerConfig1.00
SLOTightTTFTMsserver RankerConfig200ms0
SLOTightBiasserver RankerConfig1.00
TenantHotMaxAgeserver RankerConfig5m0
TenantHotMinHitRateserver RankerConfig0.1—

RenderTemplate

CodeStatus
OKEmitted (the render path is a stub returning OK today).
TEMPLATE_NOT_FOUNDSpecified; not yet emitted.
RENDER_ERRORSpecified; not yet emitted.

Ack

Ack carries no reason codes today (accepted: true, reason unset).