we-promise/sure · error · Provider::Kraken::ApiError
Malformed Kraken API response: missing result
Error message
Malformed Kraken API response: missing result
What it means
Raised as Provider::Kraken::ApiError when a 2xx Kraken response is a valid Hash with an (empty) 'error' array but no 'result' key. Per Kraken's contract, a success is {error: [], result: ...}; reaching this guard means the call was neither an in-band error (those were classified into AuthenticationError/RateLimitError/NonceError/etc.) nor a normal success — the payload is structurally a success envelope missing its payload. This is the last of three shape guards in handle_response.
Source
Thrown at app/models/provider/kraken.rb:138
parsed = response.parsed_response
unless response.code.between?(200, 299)
raise ApiError, "Kraken API request failed: #{response.code}"
end
unless parsed.is_a?(Hash)
raise ApiError, "Malformed Kraken API response"
end
unless parsed.key?("error")
raise ApiError, "Malformed Kraken API response: missing error"
end
errors = Array(parsed["error"]).reject(&:blank?)
raise classified_error(errors) if errors.any?
unless parsed.key?("result")
raise ApiError, "Malformed Kraken API response: missing result"
end
parsed["result"]
end
def classified_error(errors)
message = errors.join(", ")
case message
when /Invalid key|Invalid signature|Temporary lockout/i
AuthenticationError.new(message)
when /Invalid nonce/i
NonceError.new(message)
when /Permission denied|Invalid permissions/i
PermissionError.new(message)
when /Rate limit exceeded|Too many requests|limit exceeded|Throttled/i
RateLimitError.new(message)
when /otp|2fa|two.factor/iView on GitHub (pinned to e69894adb9)
Solutions
- Reproduce with curl and inspect the full body: does 'result' exist at top level for this endpoint?
- Check whether a proxy or response-size limit is truncating large Kraken responses (balance/trade history payloads are big)
- Retry transiently — truncation artifacts usually resolve on a second attempt
- Fix test stubs to include a 'result' key with the expected payload shape
- If Kraken genuinely changed the envelope, update handle_response to read the new location of the payload
Example fix
# before (test stub) — passes error check, then fails 'missing result'
stub_request(:post, %r{api.kraken.com}).to_return(body: {error: []}.to_json)
# after — complete success envelope
stub_request(:post, %r{api.kraken.com}).to_return(body: {error: [], result: {"ZUSD": "100.0"}}.to_json) Defensive patterns
Strategy: type-guard
Type guard
# Treat success only when the envelope is complete and result is present
def kraken_success?(parsed)
parsed.is_a?(Hash) && parsed["error"].is_a?(Array) && parsed["error"].empty? && parsed.key?("result")
end Try / catch
begin
result = provider.get_ledgers
rescue Provider::Kraken::ApiError => e
raise unless e.message.include?("missing result")
# truncated payloads: retry once, then alert — indicates gateway truncation or contract change
sleep 2
retry
end Prevention
- Include a 'result' key (even {}) in all Kraken test stubs
- Watch response sizes through proxies — large Ledger/TradesHistory payloads are the usual truncation victims
- Retry once on 'missing result': truncation is often transient
- Alert if persistent: upstream may have moved the payload to a new field
When it happens
Trigger: Any Kraken request returning {error: [], ...} without 'result' — typically partial responses from a gateway, truncated JSON that still parsed, an upstream envelope change, or test stubs returning only {error: []}. Note some Kraken endpoints legitimately return result: {} (present but empty), which does NOT trigger this; the key itself must be absent.
Common situations: Truncated responses from proxies under load, Kraken API changes relocating the payload, incomplete test stubs, and HTTParty parsing edge cases where a cut-off body still yields a Hash without the later keys.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed Kraken API response: missing error
- Malformed Kraken API response
- Unexpected response format from search API
- Unexpected response format from EOD API
- Unexpected Frankfurter response shape
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/6375fd19387e1260.
Report an issue: GitHub.