{"record":{"id":"d5f93b92d8e91107","repo":"we-promise/sure","slug":"api-error-response-code","errorCode":null,"errorMessage":"API error: #{response.code}","messagePattern":"API error: #(.+?)","errorType":"exception","errorClass":"Provider::Binance::InvalidSymbolError","httpStatus":null,"severity":"error","filePath":"app/models/provider/binance.rb","lineNumber":187,"sourceCode":"    end\n\n    def auth_headers\n      { \"X-MBX-APIKEY\" => api_key }\n    end\n\n    def handle_response(response)\n      parsed = response.parsed_response\n\n      case response.code\n      when 200..299\n        parsed\n      when 401\n        raise AuthenticationError, extract_error_message(parsed) || \"Unauthorized\"\n      when 429\n        raise RateLimitError, \"Rate limit exceeded\"\n      else\n        msg = extract_error_message(parsed) || \"API error: #{response.code}\"\n        raise InvalidSymbolError, msg if parsed.is_a?(Hash) && parsed[\"code\"] == -1121\n        raise ApiError, msg\n      end\n    end\n\n    def extract_error_message(parsed)\n      return parsed if parsed.is_a?(String)\n      return nil unless parsed.is_a?(Hash)\n      parsed[\"msg\"] || parsed[\"message\"] || parsed[\"error\"]\n    end\nend\n","sourceCodeStart":169,"sourceCodeEnd":198,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/binance.rb#L169-L198","documentation":"Raised at binance.rb:187 when a non-2xx Binance response body is a Hash whose \"code\" equals -1121 — Binance's \"Invalid symbol\" error code. The raised class is Provider::Binance::InvalidSymbolError (subclass of ApiError), carrying the Binance msg (the template \"API error: #{response.code}\" is only the fallback if the body has no msg). It fires before the generic ApiError on line 188.","triggerScenarios":"Requesting klines, ticker, or account-filtered data for a trading pair Binance does not list (e.g. \"BTCUSD\" instead of \"BTCUSDT\", \"DOGE-EUR\" where no such book exists); a delisted or renamed pair; a symbol built from the wrong quote asset; securities imported from another exchange/MIC being passed to the Binance provider unchanged.","commonSituations":"Mixing symbol conventions across providers (Tiingo/EODHD style \"BTC-USD\" vs Binance \"BTCUSDT\"); a Security record whose symbol predates a delisting; automated import pipelines that assume every crypto symbol trades on Binance; typos in manual symbol entry.","solutions":["Normalize the symbol to Binance's format (base+quote concatenated, e.g. BTCUSDT) before calling.","Verify the pair exists: GET /api/v3/exchangeInfo?symbols=[\"BTCUSDT\"] and check it is returned.","If the coin was delisted, remove or re-map the Security so it stops syncing from Binance.","Catch Provider::Binance::InvalidSymbolError specifically so one bad symbol does not abort a batch sync."],"exampleFix":"# before\nklines = provider.fetch_security_prices(symbol: \"BTC-USD\", exchange_operating_mic: \"BINANCE\", start_date: from, end_date: to) # -1121\n\n# after\nbinance_symbol = \"BTC-USD\".delete(\"-\") # => \"BTCUSD\" / use \"BTCUSDT\" for USD quotes\nklines = provider.fetch_security_prices(symbol: binance_symbol, exchange_operating_mic: \"BINANCE\", start_date: from, end_date: to)","handlingStrategy":"validation","validationCode":"INVALID = -1121\n# Pre-check against Binance's own symbol list before syncing\npairs = JSON.parse(Net::HTTP.get(URI(\"https://api.binance.com/api/v3/exchangeInfo\")))\nvalid = pairs[\"symbols\"].map { |s| s[\"symbol\"] }.to_set\nraise ArgumentError, \"#{sym} not listed on Binance\" unless valid.include?(sym.delete(\"-\"))","typeGuard":"def binance_invalid_symbol?(err)\n  err.is_a?(Provider::Binance::InvalidSymbolError)\nend","tryCatchPattern":"begin\n  klines = provider.fetch_security_prices(symbol: sym, exchange_operating_mic: mic, start_date: from, end_date: to)\nrescue Provider::Binance::InvalidSymbolError => e\n  Rails.logger.warn(\"Skipping #{sym}: #{e.message}\")\n  next\nend","preventionTips":["Normalize symbols to Binance base+quote concatenation (BTCUSDT) before calling.","Only route securities whose exchange_operating_mic is Binance to this provider.","Rescue InvalidSymbolError separately from ApiError so bad symbols skip instead of aborting batches.","Re-verify symbol lists after delistings/renames when -1121 suddenly appears."],"tags":["binance","invalid-symbol","error-code-1121","crypto"],"backgroundTag":"invalid-symbol","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}