we-promise/sure · error · Error

bad_response

bad_response

Error message

Invalid JSON in response: #{e.message}

What it means

A 200/201 response from api.indexacapital.com whose body is not valid JSON (JSON::ParserError), re-raised as Error(:bad_response) with the parser's message embedded. The raw body itself is not included in the error - only e.message's parser detail - so diagnosis leans on the message shape ('unexpected token at ...' usually means HTML).

Source

Thrown at app/models/provider/indexa_capital.rb:198

          username: username,
          document: document,
          password: password
        }.to_json
      )
      payload = handle_response(response)
      jwt = payload[:token]
      raise AuthenticationError.new("Authentication token missing in response", :unauthorized) if jwt.blank?

      jwt
    end

    def handle_response(response)
      case response.code
      when 200, 201
        begin
          JSON.parse(response.body, symbolize_names: true)
        rescue JSON::ParserError => e
          raise Error.new("Invalid JSON in response: #{e.message}", :bad_response)
        end
      when 400
        Rails.logger.error "IndexaCapital API: Bad request - #{response.body}"
        raise Error.new("Bad request: #{response.body}", :bad_request)
      when 401
        raise AuthenticationError.new("Invalid credentials", :unauthorized)
      when 403
        raise AuthenticationError.new("Access forbidden - check your permissions", :access_forbidden)
      when 404
        raise Error.new("Resource not found", :not_found)
      when 429
        raise Error.new("Rate limit exceeded. Please try again later.", :rate_limited)
      when 500..599
        raise Error.new("IndexaCapital server error (#{response.code}). Please try again later.", :server_error)
      else
        Rails.logger.error "IndexaCapital API: Unexpected response - Code: #{response.code}, Body: #{response.body}"
        raise Error.new("Unexpected error: #{response.code} - #{response.body}", :unknown)
      end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Match on the parser detail in e.message: 'unexpected token at \'<\'' almost always means an HTML page came back
  2. Retry once after a short delay - interstitials are typically one-shot
  3. Add the raw body to the error message (it is currently dropped) and capture it via DebugLogEntry for support
  4. Verify no intermediary (proxy, SSL inspection) sits between the app and api.indexacapital.com

Example fix

# app/models/provider/indexa_capital.rb - handle_response
# before
rescue JSON::ParserError => e
  raise Error.new("Invalid JSON in response: #{e.message}", :bad_response)

# after
rescue JSON::ParserError => e
  raise Error.new("Invalid JSON in response: #{e.message} - body: #{response.body.to_s[0, 200]}", :bad_response)
Defensive patterns

Strategy: try-catch

Type guard

def indexa_bad_response?(error)
  error.is_a?(Provider::IndexaCapital::Error) && error.error_type == :bad_response
end

Try / catch

begin
  provider.list_accounts
rescue Provider::IndexaCapital::Error => e
  raise unless e.error_type == :bad_response
  retry if (retries += 1) <= 1 && e.message.include?("<") # HTML interstitial: one retry
  raise
end

Prevention

When it happens

Trigger: A WAF/CDN in front of the API returns a 200 HTML challenge or banner page; the connection drops mid-body leaving truncated JSON; an SSL-inspection proxy rewrites responses; a maintenance interstitial served with 200.

Common situations: Bot-challenge pages hitting datacenter IPs, corporate proxies injecting HTML notices, flaky networking truncating large /portfolio responses.

Understand the failure class

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/c43132164585ea40. Report an issue: GitHub.