# Phase 11 — Errors module rename and retarget **Estimated time:** ~15 minutes **Touches:** `lib/dispatch/adapter/minimax/errors.rb` and every file that references `ClaudeErrors` or `OverloadedError`. ## Goal The errors module is currently `Dispatch::Adapter::ClaudeErrors`. Rename it to `Dispatch::Adapter::MiniMaxErrors`. The mapping logic (401/403 → AuthenticationError, 429 → RateLimitError, 529 → OverloadedError, 400/422 → RequestError, 5xx → ServerError) stays the same. Update the `PROVIDER` constant. The class `OverloadedError < RateLimitError` stays — Anthropic uses 529 to signal overload and MiniMax MAY too; even if MiniMax never sends 529, the class is harmless dead branch coverage. ## Steps ### 1. Rewrite `lib/dispatch/adapter/minimax/errors.rb` ```ruby # frozen_string_literal: true module Dispatch module Adapter class OverloadedError < RateLimitError; end module MiniMaxErrors module_function PROVIDER = "MiniMax" def handle_response!(response) return if response.is_a?(Net::HTTPSuccess) code = response.code.to_i msg = parse_message(response.body) retry_after = response["Retry-After"]&.to_i case code when 401, 403 then raise AuthenticationError.new(msg, status_code: code, provider: PROVIDER) when 429 then raise RateLimitError.new(msg, status_code: code, provider: PROVIDER, retry_after:) when 529 then raise OverloadedError.new(msg, status_code: code, provider: PROVIDER, retry_after:) when 400, 422 then raise RequestError.new(msg, status_code: code, provider: PROVIDER) when 500..599 then raise ServerError.new(msg, status_code: code, provider: PROVIDER) else raise Error.new(msg, status_code: code, provider: PROVIDER) end end def parse_message(body) parsed = JSON.parse(body.to_s) # Anthropic shape: {"error":{"message":"..."}} # MiniMax may also use the same shape; keep the dig. return parsed.dig("error", "message").to_s unless parsed.dig("error", "message").nil? # Fallback: top-level "message" key (some MiniMax surfaces use this). return parsed["message"].to_s if parsed["message"] body.to_s rescue JSON::ParserError body.to_s end end end end ``` Notes on `parse_message`: - Adds a fallback for a top-level `"message"` key. We don't yet know MiniMax's exact error JSON shape, but supporting both `{error:{message}}` and `{message}` is cheap and forwards-compatible. - If neither matches, falls back to the raw body. ### 2. Find every reference to `ClaudeErrors` and update ```bash grep -rn 'ClaudeErrors\|ClaudeErrors::PROVIDER' lib/ spec/ sig/ ``` Replace each occurrence with `MiniMaxErrors`. Common locations: - `lib/dispatch/adapter/minimax/sse_parser.rb` (`raise RequestError.new(..., provider: ClaudeErrors::PROVIDER)`) - `lib/dispatch/adapter/minimax/http_client.rb` - `lib/dispatch/adapter/minimax/stream_collector.rb` - `lib/dispatch/adapter/minimax/usage_client.rb` — DELETED in phase 02, shouldn't appear, but double-check. - `lib/dispatch/adapter/minimax.rb` (top-level adapter) Also confirm the rbs sig file mirrors the rename: ```bash grep -n 'ClaudeErrors' sig/dispatch/adapter/minimax.rbs ``` If there's a sig declaration for `ClaudeErrors`, rename to `MiniMaxErrors`. ### 3. Confirm `errors.rb` is required `lib/dispatch/adapter/minimax.rb` should have `require_relative "minimax/errors"` near the top of its requires list. If phase 01 left it as `require_relative "minimax/errors"` already, no change needed. The new module name `MiniMaxErrors` is autoloaded via that file. ## Acceptance criteria - `grep -rn 'ClaudeErrors' lib/ spec/ sig/` returns ZERO matches. - `Dispatch::Adapter::MiniMaxErrors::PROVIDER == "MiniMax"`. - `Dispatch::Adapter::MiniMaxErrors.handle_response!(...)` raises the correct mapped error class for each status code as documented above. - `parse_message('{"error":{"message":"oops"}}') == "oops"`. - `parse_message('{"message":"oops"}') == "oops"`. - `parse_message("not json") == "not json"`. - `bundle exec rubocop --autocorrect-all` exits 0. ## Verification Run `run_tests` with `project_path=reference/dispatch-adapter-minimax`. Rubocop must be clean. `errors_spec.rb` failures referencing `ClaudeErrors` are addressed in phase 16. Failures NOT explainable by that rename must be fixed before calling `ask_for_next_plan`.