freqtrade/freqtrade · critical · OperationalException

The ccxt library does not provide the list of timeframes for

Error message

The ccxt library does not provide the list of timeframes for the exchange {self.name} and this exchange is therefore not supported. ccxt fetchOHLCV: {self.exchange_has('fetchOHLCV')}

What it means

Raised in validate_timeframes() during startup when the ccxt exchange class exposes no timeframes attribute (or it is None). Without that list freqtrade cannot verify the configured timeframe, which almost always means the exchange has no fetchOHLCV support at all. The message includes exchange_has('fetchOHLCV') to make that diagnosis immediate. This is an OperationalException: the exchange subclass is fundamentally incompatible with freqtrade's data model.

Source

Thrown at freqtrade/exchange/exchange.py:790

            f"{curr_2}/{curr_1}",
            f"{curr_1}/{curr_2}:{curr_2}",
            f"{curr_2}/{curr_1}:{curr_1}",
        ):
            if pair in self.markets and self.markets[pair].get("active"):
                yielded = True
                yield pair
        if not yielded:
            raise ValueError(f"Could not combine {curr_1} and {curr_2} to get a valid pair.")

    def validate_timeframes(self, timeframe: str | None) -> None:
        """
        Check if timeframe from config is a supported timeframe on the exchange
        """
        if not hasattr(self._api, "timeframes") or self._api.timeframes is None:
            # If timeframes attribute is missing (or is None), the exchange probably
            # has no fetchOHLCV method.
            # Therefore we also show that.
            raise OperationalException(
                f"The ccxt library does not provide the list of timeframes "
                f"for the exchange {self.name} and this exchange "
                f"is therefore not supported. ccxt fetchOHLCV: {self.exchange_has('fetchOHLCV')}"
            )

        if timeframe and (timeframe not in self.timeframes):
            raise ConfigurationError(
                f"Invalid timeframe '{timeframe}'. This exchange supports: {self.timeframes}"
            )

        if (
            timeframe
            and self._config["runmode"] != RunMode.UTIL_EXCHANGE
            and timeframe_to_minutes(timeframe) < 1
        ):
            raise ConfigurationError("Timeframes < 1m are currently not supported by Freqtrade.")

    def validate_ordertypes(self, order_types: dict) -> None:

View on GitHub (pinned to 1c8edfe4d1)

Solutions

  1. Switch exchange.name to a fully supported exchange (binance, kraken, bybit, etc.).
  2. Upgrade ccxt to a version where the target exchange implements fetchOHLCV and timeframes.
  3. If writing a custom exchange subclass, ensure _ft_has and the underlying ccxt class provide timeframes/fetchOHLCV.

Example fix

# config.json - before
"exchange": { "name": "somefeed", ... }

# after
"exchange": { "name": "binance", ... }
Defensive patterns

Strategy: validation

Validate before calling

import ccxt
api = getattr(ccxt, exchange_name)()
if not getattr(api, 'has', {}).get('fetchOHLCV') or not getattr(api, 'timeframes', None):
    raise SystemExit(f"{exchange_name} cannot provide OHLCV; pick another exchange")

Prevention

When it happens

Trigger: Configuring an exchange whose ccxt implementation lacks OHLCV (fetchOHLCV false), or a mocked/partial ccxt class without a timeframes member, then running validate_timeframes during Exchange initialization (any live/dry/util runmode).

Common situations: User points config at a niche or newly added ccxt exchange that only supports tickers/trades; a custom exchange subclass overrides _api with a stub; ccxt version change removed/renamed the timeframes property.

Related errors


AI-assisted analysis of freqtrade/freqtrade@1c8edfe4d1 (2026-08-15). Data as JSON: /api/errors/eafb77102e0d3b47. Report an issue: GitHub.