apache/superset · error · AsyncQueryTokenException

Token not preset

Error message

Token not preset

What it means

AsyncQueryTokenException('Token not preset') ('preset' is a typo for 'present' in the source) is raised by parse_channel_id_from_request() when the async-queries JWT cookie named by GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME is absent from the request. With GAQ enabled, every chart-data request must carry this cookie so Superset knows which Redis stream channel to publish events to; guest users bypass it via a derived channel id.

Source

Thrown at superset/async_events/async_query_manager.py:273

                "rev": token.get("rev"),
            },
            sort_keys=True,
        ).encode("utf-8")
        digest = hmac.new(
            self._jwt_secret.encode("utf-8"), message, hashlib.sha256
        ).hexdigest()
        return f"guest-{digest}"

    def parse_channel_id_from_request(self, req: Request) -> str:
        # pylint: disable=import-outside-toplevel
        from superset import security_manager

        if guest_user := security_manager.get_current_guest_user_if_guest():
            return self.get_guest_user_channel_id(guest_user)

        token = req.cookies.get(self._jwt_cookie_name)
        if not token:
            raise AsyncQueryTokenException("Token not preset")

        try:
            return jwt.decode(token, self._jwt_secret, algorithms=["HS256"])["channel"]
        except Exception as ex:
            logger.warning("Parse jwt failed", exc_info=True)
            raise AsyncQueryTokenException("Failed to parse token") from ex

    def init_job(self, channel_id: str, user_id: Optional[int]) -> dict[str, Any]:
        job_id = str(uuid.uuid4())
        self._register_cancellable_job(job_id, channel_id, user_id)
        return build_job_metadata(
            channel_id, job_id, user_id, status=self.STATUS_PENDING
        )

    def _job_registry_key(self, job_id: str) -> str:
        return f"{self._stream_prefix}{self._JOB_REGISTRY_PREFIX}{job_id}"

    def _register_cancellable_job(

View on GitHub (pinned to f4587218dd)

Solutions

  1. For API clients: first request a session (login) the same way the UI does so the async token cookie is issued, then replay it with the cookie jar on subsequent requests.
  2. For browsers: log out and back in (or clear cookies) after enabling GLOBAL_ASYNC_QUERIES so the JWT cookie gets set; verify GLOBAL_ASYNC_QUERIES_JWT_COOKIE_DOMAIN/secure/samesite settings match your deployment (HTTPS vs HTTP).
  3. Confirm you are not stripping cookies at a proxy/load balancer.

Example fix

# before (python client)
requests.post(url, json=payload)  # no cookies -> Token not preset

# after
import requests
s = requests.Session()
s.auth = (user, pwd)  # or s.post(login_url, ...)
s.get("http://superset:8088/api/v1/chart/data")  # establishes cookies
resp = s.post("http://superset:8088/api/v1/chart/data", json=payload)
Defensive patterns

Strategy: try-catch

Validate before calling

cookie_name = app.config["GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME"]
if not request.cookies.get(cookie_name) and not current_user.is_guest:
    # re-establish session: hit the app once so the token cookie is issued
    return reauthenticate()

Try / catch

from superset.async_events.async_query_manager import AsyncQueryTokenException
try:
    channel_id = manager.parse_channel_id_from_request(request)
except AsyncQueryTokenException:
    # 401: client must (re)login to obtain the async token cookie
    return response_401()

Prevention

When it happens

Trigger: Calling the chart data / async endpoints with curl, requests, or a script (no cookie jar) while GLOBAL_ASYNC_QUERIES is enabled; browser sessions where the cookie was never set because the user authenticated before the feature was turned on, the cookie domain/path config is wrong, or cookies are blocked.

Common situations: See trigger scenarios.

Related errors


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