gate_io_perpetual candles feed: TypeError due to uninitialized quanto_multiplier
Describe the bug
The gate_io_perpetual candles feed crashes with TypeError: unsupported operand type(s) for *: 'int' and 'NoneType' when fetch_candles() or WebSocket candle streaming is called before initialize_exchange_data() has completed.
Root Cause
In hummingbot/data_feed/candles_feed/gate_io_perpetual_candles/gate_io_perpetual_candles.py:
self.quanto_multiplieris initialized asNonein__init__- It only gets set when
initialize_exchange_data()is called, which fetches the quanto multiplier from the Gate.io API viaget_exchange_trading_pair_quanto_multiplier() - Both
_parse_rest_candlesand_parse_websocket_messagemultiply volume byself.quanto_multiplier:volume = i.get("v") * self.quanto_multiplier # TypeError if quanto_multiplier is None - If
fetch_candles()is called beforeinitialize_exchange_data()completes (e.g. during validation or when a consumer calls the candle feed immediately after creation), the multiplication fails
Error Message
Trading pair 'BTC-USDT' appears to be invalid on 'gate_io_perpetual':
unsupported operand type(s) for *: 'int' and 'NoneType'This error is misleading — the trading pair is valid, but the feed hasn't initialized its exchange data yet.
Impact
- Candle charts: No chart data is rendered for any
gate_io_perpetualtrading pair in downstream consumers (e.g. Condor web dashboard, hummingbot-api) - WebSocket streams: Candle WS subscriptions fail permanently because hummingbot-api's
validate_trading_pair()creates a fresh feed viaCandlesFactory.get_candle()and immediately callsfetch_candles()without awaitinginitialize_exchange_data() - Spot works fine:
gate_io(spot) candles feed does not have aquanto_multiplierand is unaffected
Suggested Fix
Option A (in the candles feed itself — preferred):
Default quanto_multiplier to 1 instead of None, and/or call initialize_exchange_data() inside fetch_candles() if not yet initialized:
# In __init__:
self.quanto_multiplier = 1 # Safe default until exchange data is fetched
# Or guard in _parse_rest_candles / _parse_websocket_message:
multiplier = self.quanto_multiplier if self.quanto_multiplier is not None else 1
volume = i.get("v") * multiplierOption B (in consumers like hummingbot-api):
Call await feed.initialize_exchange_data() before fetch_candles():
feed = CandlesFactory.get_candle(config)
if hasattr(feed, 'initialize_exchange_data'):
await feed.initialize_exchange_data()
candles = await feed.fetch_candles(end_time=end_time, limit=1)Option A is preferred because the candles feed should be resilient to its own initialization order.
Steps to reproduce
- Start hummingbot-api with Gate.io perpetual credentials configured
- Make a REST API call to fetch candles for
gate_io_perpetualwith any valid pair:POST /market-data/candles {"connector_name": "gate_io_perpetual", "trading_pair": "BTC-USDT", "interval": "1m", "max_records": 10} - Or subscribe via WebSocket:
{"action": "subscribe", "type": "candles", "connector": "gate_io_perpetual", "trading_pair": "BTC-USDT", "interval": "1m"} - The request fails with:
Trading pair 'BTC-USDT' appears to be invalid on 'gate_io_perpetual': unsupported operand type(s) for *: 'int' and 'NoneType' - Compare with
gate_io(spot) — works correctly
Release version
Latest (pip install hummingbot, tested July 2026)
Type of installation
Source (via pip in conda environment, used with hummingbot-api)
Additional context
- The same bug pattern likely affects other perpetual connectors that use
quanto_multiplier(e.g.binance_perpetualif it has the same field) - Workaround applied in hummingbot-api fork by calling
initialize_exchange_data()beforefetch_candles()invalidate_trading_pair() - File:
hummingbot/data_feed/candles_feed/gate_io_perpetual_candles/gate_io_perpetual_candles.py
Source: hummingbot/hummingbot