apache/superset · error · UnsupportedCacheBackendError

Unsupported cache backend configuration

Error message

Unsupported cache backend configuration

What it means

UnsupportedCacheBackendError is raised by get_cache_backend() (async query manager setup) when GLOBAL_ASYNC_QUERIES_CACHE_BACKEND.CACHE_TYPE in Flask config is neither 'RedisCache' nor 'RedisSentinelCache'. Global async queries (GAQ) stream results over Redis streams, so only those two Redis backends are implemented (the TODO in the source confirms more options are pending).

Source

Thrown at superset/async_events/async_query_manager.py:100

        return prefix + str(last + 1)
    except Exception:  # pylint: disable=broad-except
        return entry_id


def get_cache_backend(
    config: dict[str, Any],
) -> RedisCacheBackend | RedisSentinelCacheBackend:
    cache_config = config.get("GLOBAL_ASYNC_QUERIES_CACHE_BACKEND", {})
    cache_type = cache_config.get("CACHE_TYPE")

    if cache_type == "RedisCache":
        return RedisCacheBackend.from_config(cache_config)

    if cache_type == "RedisSentinelCache":
        return RedisSentinelCacheBackend.from_config(cache_config)

    # TODO: Expand cache backend options.
    raise UnsupportedCacheBackendError("Unsupported cache backend configuration")


class AsyncQueryManager:
    MAX_EVENT_COUNT = 100
    STATUS_PENDING = "pending"
    STATUS_RUNNING = "running"
    STATUS_ERROR = "error"
    STATUS_DONE = "done"
    STATUS_CANCELLED = "cancelled"
    # Redis key prefix (within the GAQ stream namespace) for the per-job record
    # that authorizes cancellation and flags a job as cancelled for the worker.
    _JOB_REGISTRY_PREFIX = "job-cancel:"

    def __init__(self) -> None:
        super().__init__()
        self._cache: Optional[BaseCache] = None
        self._stream_prefix: str = ""
        self._stream_limit: Optional[int]

View on GitHub (pinned to f4587218dd)

Solutions

  1. Set GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {"CACHE_TYPE": "RedisCache", "CACHE_URL": "redis://..."} in superset_config.py (or RedisSentinelCache with sentinel config).
  2. Keep GAQ on a dedicated Redis instance/database from the metadata cache, per the async queries docs.
  3. Until you have Redis available, leave GLOBAL_ASYNC_QUERIES disabled (the default) so the backend factory is never invoked.

Example fix

# before (superset_config.py)
GLOBAL_ASYNC_QUERIES_JWT_SECRET = "..."
FEATURE_FLAGS = {"GLOBAL_ASYNC_QUERIES": True}
# GAQ cache backend unset -> UnsupportedCacheBackendError

# after
GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {
    "CACHE_TYPE": "RedisCache",
    "CACHE_URL": "redis://my-redis:6379/2",
}
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {"RedisCache", "RedisSentinelCache"}
gaq = config.get("GLOBAL_ASYNC_QUERIES_CACHE_BACKEND", {})
if gaq.get("CACHE_TYPE") not in SUPPORTED:
    raise SystemExit("Set GLOBAL_ASYNC_QUERIES_CACHE_BACKEND CACHE_TYPE to RedisCache or RedisSentinelCache")

Prevention

When it happens

Trigger: Enabling GLOBAL_ASYNC_QUERIES in superset_config.py while GLOBAL_ASYNC_QUERIES_CACHE_BACKEND is left as the default {} (CACHE_TYPE None) or set to something like 'SimpleCache', 'FileSystemCache', or 'MemoryCache'. Also setting only CACHE_CONFIG/DATA_CACHE_CONFIG to Redis but not the GAQ-specific block.

Common situations: Operators enabling async queries for the first time and assuming the general CACHE_CONFIG applies to GAQ; staging setups using SimpleCache locally then flipping the feature flag on; upgrades where the GAQ config block was dropped during config refactoring.

Related errors


AI-assisted analysis of apache/superset@f4587218dd (2026-08-14). Data as JSON: /api/errors/5727ae38f5c3871f. Report an issue: GitHub.