Module: Ghostcrawl::ErrorCodes

Defined in:
lib/ghostcrawl/error_codes.rb

Overview

Canonical error-code constants + lookup tables. The 23 codes, their HTTP status, retryability, and channel mirror the server-side catalog so that every typed error the SDK raises carries a stable, documented code.

Constant Summary collapse

BAD_REQUEST =

--- PROBLEM channel (our failure -> non-2xx) ----------------------------

"bad_request"
UNAUTHORIZED =
"unauthorized"
FORBIDDEN =
"forbidden"
PAYMENT_REQUIRED =
"payment_required"
NOT_FOUND =
"not_found"
CONFLICT =
"conflict"
BYO_PROXY_INVALID =
"byo_proxy_invalid"
TIER_UNAVAILABLE =
"tier_unavailable"
RATE_LIMITED =
"rate_limited"
QUOTA_BACKEND_UNAVAILABLE =
"quota_backend_unavailable"
POOL_EXHAUSTED =
"pool_exhausted"
EGRESS_INTEGRITY_FAILED =
"egress_integrity_failed"
RENDER_HUNG =
"render_hung"
ENGINE_CRASHED =
"engine_crashed"
RENDER_TIMEOUT =
"render_timeout"
FLEET_TIMEOUT =
"fleet_timeout"
SERVICE_UNAVAILABLE =
"service_unavailable"
INTERNAL_ERROR =
"internal_error"
TARGET_HTTP_ERROR =

--- RESULT channel (target failure -> HTTP 200 + result_error) ----------

"target_http_error"
"navigation_failed"
BLOCKED =
"blocked"
CAPTCHA_REQUIRED =
"captcha_required"
EMPTY_CONTENT =
"empty_content"
CATALOG =

Full catalog: code => retryable:, channel:. Mirrors codes.json.

{
  BAD_REQUEST               => { http: 400, retryable: false, channel: "problem" },
  UNAUTHORIZED              => { http: 401, retryable: false, channel: "problem" },
  FORBIDDEN                 => { http: 403, retryable: false, channel: "problem" },
  PAYMENT_REQUIRED          => { http: 402, retryable: false, channel: "problem" },
  NOT_FOUND                 => { http: 404, retryable: false, channel: "problem" },
  CONFLICT                  => { http: 409, retryable: false, channel: "problem" },
  BYO_PROXY_INVALID         => { http: 422, retryable: false, channel: "problem" },
  TIER_UNAVAILABLE          => { http: 400, retryable: false, channel: "problem" },
  RATE_LIMITED              => { http: 429, retryable: true,  channel: "problem" },
  QUOTA_BACKEND_UNAVAILABLE => { http: 503, retryable: true,  channel: "problem" },
  POOL_EXHAUSTED            => { http: 503, retryable: true,  channel: "problem" },
  EGRESS_INTEGRITY_FAILED   => { http: 503, retryable: true,  channel: "problem" },
  RENDER_HUNG               => { http: 503, retryable: true,  channel: "problem" },
  ENGINE_CRASHED            => { http: 503, retryable: true,  channel: "problem" },
  RENDER_TIMEOUT            => { http: 504, retryable: true,  channel: "problem" },
  FLEET_TIMEOUT             => { http: 504, retryable: true,  channel: "problem" },
  SERVICE_UNAVAILABLE       => { http: 503, retryable: true,  channel: "problem" },
  INTERNAL_ERROR            => { http: 500, retryable: true,  channel: "problem" },
  TARGET_HTTP_ERROR         => { http: 200, retryable: false, channel: "result" },
  NAVIGATION_FAILED         => { http: 200, retryable: false, channel: "result" },
  BLOCKED                   => { http: 200, retryable: true,  channel: "result" },
  CAPTCHA_REQUIRED          => { http: 200, retryable: true,  channel: "result" },
  EMPTY_CONTENT             => { http: 200, retryable: false, channel: "result" }
}.freeze
RETRYABLE =

code => retryable? boolean lookup, derived from CATALOG.

CATALOG.transform_values { |meta| meta[:retryable] }.freeze
RESULT_CODES =

Codes carried on a successful (HTTP 200) response that signal a target-side failure — the RESULT channel. A top-level code is only treated as an error when it appears in this set.

CATALOG.select { |_code, meta| meta[:channel] == "result" }.keys.freeze

Class Method Summary collapse

Class Method Details

.code_for_status(status) ⇒ String

Fallback status -> canonical code map, used when the response body carries no code (the common Kiota case where the body is dropped before the adapter raises). Keeps every typed error keyed to a canonical code.

Parameters:

  • status (Integer)

    HTTP status code

Returns:

  • (String)

    canonical error code



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/ghostcrawl/error_codes.rb', line 87

def self.code_for_status(status)
  case status
  when 400 then BAD_REQUEST
  when 401 then UNAUTHORIZED
  when 402 then PAYMENT_REQUIRED
  when 403 then FORBIDDEN
  when 404 then NOT_FOUND
  when 409 then CONFLICT
  # 422 is the generic validation status the API returns for ANY malformed
  # request (its canonical code is "bad_request": missing field, failed
  # extraction validation, etc.). byo_proxy_invalid is only ONE 422 sub-case
  # and, when it genuinely occurs, arrives WITH a problem+json body carrying
  # code:"byo_proxy_invalid" (which raise_translated reads first). Using the
  # BYO-specific code as the blanket 422 fallback mislabels every unrelated
  # validation 422. Fall back to the generic bad_request instead.
  when 422 then BAD_REQUEST
  when 429 then RATE_LIMITED
  when 503 then SERVICE_UNAVAILABLE
  when 504 then FLEET_TIMEOUT
  else
    status.to_i >= 500 ? INTERNAL_ERROR : BAD_REQUEST
  end
end

.result_channel?(code) ⇒ Boolean

Whether code is a known RESULT-channel (HTTP-200 target-failure) code.

Parameters:

  • code (String, nil)

Returns:

  • (Boolean)


78
79
80
# File 'lib/ghostcrawl/error_codes.rb', line 78

def self.result_channel?(code)
  RESULT_CODES.include?(code)
end