Today every failure raises HTTP::StatusError from http.rb's :raise_error
feature. The parsed body is reachable via e.response.parse, but it is untyped,
undocumented, and the same class covers all 50 documented failure modes.
Amazon Ads publishes a closed enum, components/schemas/ErrorCode, with 50
values and a description for each:
ACTION_NOT_SUPPORTED, ACTIVE_RESOURCE_LIMIT_EXCEEDED, ARCHIVED_PARENT_CANNOT_CREATE,
ARCHIVED_RESOURCE_CANNOT_EDIT, BAD_REQUEST, CONFLICT, CONTENT_TOO_LARGE,
DUPLICATE_FIELD_VALUE_FOUND, FIELD_VALUE_IS_INVALID, FORBIDDEN, INTERNAL_ERROR,
NOT_FOUND, PAYMENT_ISSUE, PRODUCT_INELIGIBLE, RESOURCE_ID_NOT_FOUND,
TOO_MANY_REQUESTS, UNSUPPORTED_MARKETPLACE, ...
Because the enum is closed we can generate the classes at build time rather
than defining them at runtime:
module AmazonAds
class Error < StandardError
attr_reader :response
def status = response&.status&.code
def deconstruct_keys(keys) = { status:, code: }
end
module Errors
# Archived resources cannot be edited.
class ArchivedResourceCannotEdit < Error; end
# There have been too many requests, please slow down your call rate.
class TooManyRequests < Error; end
# ...
end
end
Generating beats runtime const_set here: the constants exist before the first
failure, they are greppable, they get RBS types, and each carries Amazon's own
description as a doc comment.
Implementation notes
- Envelope shapes differ across our specs.
amazon_ads.json and
marketing_stream.json use {code, message}; reporting.json uses
{code, detail}. A builder needs to handle both.
- With
retries: n, http.rb raises HTTP::OutOfRetriesError instead. That needs
catching and rebuilding into the same hierarchy.
- Unknown or missing codes should fall back to the base
Error rather than
raising during error construction.
Prior art
Peddler does this dynamically (lib/peddler/error/builder.rb) because SP-API
error codes are open-ended strings. We have a fixed enum, so we get to do the
better version.
Today every failure raises
HTTP::StatusErrorfrom http.rb's:raise_errorfeature. The parsed body is reachable via
e.response.parse, but it is untyped,undocumented, and the same class covers all 50 documented failure modes.
Amazon Ads publishes a closed enum,
components/schemas/ErrorCode, with 50values and a description for each:
Because the enum is closed we can generate the classes at build time rather
than defining them at runtime:
Generating beats runtime
const_sethere: the constants exist before the firstfailure, they are greppable, they get RBS types, and each carries Amazon's own
description as a doc comment.
Implementation notes
amazon_ads.jsonandmarketing_stream.jsonuse{code, message};reporting.jsonuses{code, detail}. A builder needs to handle both.retries: n, http.rb raisesHTTP::OutOfRetriesErrorinstead. That needscatching and rebuilding into the same hierarchy.
Errorrather thanraising during error construction.
Prior art
Peddler does this dynamically (
lib/peddler/error/builder.rb) because SP-APIerror codes are open-ended strings. We have a fixed enum, so we get to do the
better version.