Bug Description
classify_api_error() in openviking/utils/model_retry.py uses plain substring matching (in operator) for error pattern classification. The pattern lists include bare numeric HTTP status codes like "413", "400", "401", "403", "429", "500", etc. These numeric patterns can falsely match inside request IDs or hex strings in error messages, causing incorrect error classification.
Root Cause
When an API returns a 429 (Too Many Requests) error, the error message includes a request ID, e.g.:
Volcengine hybrid embedding failed: Error code: 429 - {'error': {'code': 'ModelAccountRpmRateLimitExceeded', ...}, 'request_id': '0217801248873024288fe53d7c9130f34413480585e683685bc95'}
The code does text_compact = text.lower().replace(" ", "") and then checks "413" in text_compact. The request ID d7c9130f344... contains the substring "413", so "413" in text_compact returns True. Since INPUT_TOO_LARGE is checked before TRANSIENT, the 429 error is misclassified as INPUT_TOO_LARGE.
In TextEmbeddingHandler.on_dequeue(), INPUT_TOO_LARGE errors are logged and permanently dropped (no re-enqueue), while TRANSIENT errors are re-enqueued for retry. This caused 2,741 embedding messages to be permanently lost during a full reindex of ~476K records.
Steps to Reproduce
from openviking.utils.model_retry import classify_api_error
# 429 error with request ID containing "413" — BUG: returns "input_too_large"
error = RuntimeError(
"Volcengine hybrid embedding failed: Error code: 429 - "
"{'error': {'code': 'ModelAccountRpmRateLimitExceeded', "
"'message': 'RPM limit exceeded', 'param': '', "
"'type': 'TooManyRequests'}, "
"'request_id': '0217801248873024288fe53d7c9130f34413480585e683685bc95'}"
)
assert classify_api_error(error) == "transient" # FAILS: returns "input_too_large"
# "400" inside "1400" — BUG: returns "permanent"
assert classify_api_error(RuntimeError("status: 1400 OK")) == "unknown" # FAILS: returns "permanent"
Expected Behavior
Numeric patterns like "413", "400", "429" etc. should only match standalone HTTP status codes, not arbitrary substrings inside request IDs or other numbers.
Suggested Fix
Replace substring matching (in) with regex word-boundary matching (\b) for numeric-only patterns in _pattern_matches(). Non-numeric text patterns (e.g., "payload too large", "forbidden") continue using substring matching since they are specific enough.
Impact
- All
classify_api_error callers are affected (embedding consumer, VLM, reranker retry logic)
- 6 numeric patterns total:
"413", "400", "401", "403", "429", "500", "502", "503", "504"
Related Issues
Bug Description
classify_api_error()inopenviking/utils/model_retry.pyuses plain substring matching (inoperator) for error pattern classification. The pattern lists include bare numeric HTTP status codes like"413","400","401","403","429","500", etc. These numeric patterns can falsely match inside request IDs or hex strings in error messages, causing incorrect error classification.Root Cause
When an API returns a 429 (Too Many Requests) error, the error message includes a request ID, e.g.:
The code does
text_compact = text.lower().replace(" ", "")and then checks"413" in text_compact. The request IDd7c9130f344...contains the substring"413", so"413" in text_compactreturnsTrue. SinceINPUT_TOO_LARGEis checked beforeTRANSIENT, the 429 error is misclassified asINPUT_TOO_LARGE.In
TextEmbeddingHandler.on_dequeue(),INPUT_TOO_LARGEerrors are logged and permanently dropped (no re-enqueue), whileTRANSIENTerrors are re-enqueued for retry. This caused 2,741 embedding messages to be permanently lost during a full reindex of ~476K records.Steps to Reproduce
Expected Behavior
Numeric patterns like
"413","400","429"etc. should only match standalone HTTP status codes, not arbitrary substrings inside request IDs or other numbers.Suggested Fix
Replace substring matching (
in) with regex word-boundary matching (\b) for numeric-only patterns in_pattern_matches(). Non-numeric text patterns (e.g.,"payload too large","forbidden") continue using substring matching since they are specific enough.Impact
classify_api_errorcallers are affected (embedding consumer, VLM, reranker retry logic)"413","400","401","403","429","500","502","503","504"Related Issues
"413"toINPUT_TOO_LARGE_PATTERNS) introduced the substring matching bug