Module: Legion::LLM::API::ErrorTranslator

Extended by:
Legion::Logging::Helper
Includes:
Legion::Logging::Helper
Included in:
Namespaces::Helpers
Defined in:
lib/legion/llm/api/error_translator.rb

Overview

G14 / D-G: Maps LLM routing errors to HTTP responses.

NoLaneAvailable → 400 (filters excluded everything; caller can fix the request) EscalationExhausted → 503 + Retry-After (tried lanes, all failed; transient upstream degradation) InvalidHeader → 400 (x-legion-* header carries unrecognized value; caller can fix)

Included into API Helpers so every inference route gets the mapping without duplicating rescue clauses. Must be included BEFORE the route-level rescue for StandardError so callers see the typed 400/503 rather than a 500.

Instance Method Summary collapse

Instance Method Details

#translate_escalation_exhausted(error, operation:) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/legion/llm/api/error_translator.rb', line 35

def translate_escalation_exhausted(error, operation:, **)
  handle_exception(error, level: :warn, handled: true, operation: operation)
  # opus M5: read from settings; no inline || literal at the read site.
  retry_after = Legion::Settings[:llm][:api][:escalation_exhausted_retry_after]
  headers 'Retry-After' => retry_after.to_s
  body = {
    error: {
      type:              'escalation_exhausted',
      message:           error.message,
      attempts:          error.respond_to?(:attempts) ? error.attempts : 0,
      tried_lanes_count: Array(error.respond_to?(:tried_lanes) ? error.tried_lanes : []).size
    }
  }
  content_type :json
  status 503
  Legion::JSON.dump(body)
end

#translate_invalid_header(error, operation:) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/legion/llm/api/error_translator.rb', line 53

def translate_invalid_header(error, operation:, **)
  handle_exception(error, level: :warn, handled: true, operation: operation)
  body = {
    error: {
      type:    'invalid_header',
      message: error.message,
      header:  error.respond_to?(:header) ? error.header : nil,
      got:     error.respond_to?(:got)    ? error.got    : nil,
      valid:   error.respond_to?(:valid)  ? error.valid  : []
    }.compact
  }
  content_type :json
  status 400
  Legion::JSON.dump(body)
end

#translate_no_lane_available(error, operation:) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/legion/llm/api/error_translator.rb', line 21

def translate_no_lane_available(error, operation:, **)
  handle_exception(error, level: :warn, handled: true, operation: operation)
  body = {
    error: {
      type:    'no_lane_available',
      message: error.message,
      filters: error.respond_to?(:filters) ? error.filters : {}
    }
  }
  content_type :json
  status 400
  Legion::JSON.dump(body)
end