Freika/dawarich · error · AirTrail::Client::Error

AirTrail responded with #{response.code}

Error message

AirTrail responded with #{response.code}

What it means

AirTrail::Client#flights GETs {url}/api/flight/list?scope=... with a Bearer API key and a 15-second timeout; any non-2xx HTTP status raises AirTrail::Error with the numeric code embedded ('AirTrail responded with 401'). HTTParty errors, connection timeouts, and JSON parse failures are rescued separately and re-raised as Error with the underlying message - this particular message is exclusively the HTTP-status branch.

Source

Thrown at app/services/air_trail/client.rb:27

    def initialize(url, api_key, skip_ssl_verification: false)
      @url = url.to_s.chomp('/')
      @api_key = api_key
      @skip_ssl_verification = skip_ssl_verification
    end

    def flights(scope: 'mine')
      response = HTTParty.get(
        "#{@url}/api/flight/list?scope=#{scope}",
        http_options_with_ssl_flag(@skip_ssl_verification, {
                                     headers: {
                                       'Authorization' => "Bearer #{@api_key}",
                                       'accept' => 'application/json'
                                     },
                                     timeout: 15
                                   })
      )

      raise Error, "AirTrail responded with #{response.code}" unless response.success?

      body = JSON.parse(response.body)
      raise Error, 'AirTrail returned an unsuccessful response' unless body['success']

      body['flights'] || []
    rescue HTTParty::Error, Net::OpenTimeout, Net::ReadTimeout, JSON::ParserError => e
      raise Error, e.message
    end
  end
end

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Match the number: 401 -> fix the API key, 404 -> fix the URL/version, 403 -> key permissions/scope, 5xx -> AirTrail side is unhealthy
  2. curl -H 'Authorization: Bearer <key>' {url}/api/flight/list?scope=mine to see the raw response outside Dawarich
  3. Confirm the AirTrail instance version actually exposes /api/flight/list
  4. Check the skip_ssl_verification setting matches the instance's certificate setup
Defensive patterns

Strategy: try-catch

Try / catch

begin
  AirTrail::Client.new(url:, api_key:, skip_ssl_verification:).flights(scope: 'mine')
rescue AirTrail::Error => e
  Rails.logger.warn("AirTrail sync failed: #{e.message}")
  # report to the user; do not retry blindly - 401/404 are deterministic failures
end

Prevention

When it happens

Trigger: 401 when the configured AirTrail API key is wrong/revoked, 404 when the base URL points to an AirTrail instance whose version lacks /api/flight/list (older/self-hosted forks), 403 when the key's account cannot use scope=mine, 5xx when the AirTrail server is down or reverse-proxied to nothing.

Common situations: Typo in the AIRTRAIL_URL setting (missing / trailing path so the joined route 404s), rotated AirTrail API key not updated in Dawarich settings, self-hosted AirTrail upgraded/changed its API surface, TLS-terminating proxy returning 502 while the upstream restarts, scope parameter values the target instance does not support.

Related errors


AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21). Data as JSON: /api/errors/dbf3f4b130ae5fca. Report an issue: GitHub.