mlflow/mlflow · error · MlflowException

AsyncLoggingQueue is not activated.

Error message

AsyncLoggingQueue is not activated.

What it means

AsyncLoggingQueue.log_batch_async checks `is_active()` before enqueueing a RunBatch. If the queue's consumer thread was never started (`start()` not called) or has been stopped/terminated, MLflow raises MlflowException because there is no worker to consume the batch. This fails fast to avoid silently losing logged metrics, params, or tags.

Source

Thrown at mlflow/utils/async_logging/async_logging_queue.py:305

        """Asynchronously logs a batch of run data (parameters, tags, and metrics).

        Args:
            run_id (str): The ID of the run to log data for.
            params (list[mlflow.entities.Param]): A list of parameters to log for the run.
            tags (list[mlflow.entities.RunTag]): A list of tags to log for the run.
            metrics (list[mlflow.entities.Metric]): A list of metrics to log for the run.

        Returns:
            mlflow.utils.async_utils.RunOperations: An object that encapsulates the
                asynchronous operation of logging the batch of run data.
                The object contains a list of `concurrent.futures.Future` objects that can be used
                to check the status of the operation and retrieve any exceptions
                that occurred during the operation.
        """
        from mlflow import MlflowException

        if not self.is_active():
            raise MlflowException("AsyncLoggingQueue is not activated.")
        batch = RunBatch(
            run_id=run_id,
            params=params,
            tags=tags,
            metrics=metrics,
            completion_event=threading.Event(),
        )
        self._queue.put(batch)
        operation_future = self._batch_status_check_threadpool.submit(self._wait_for_batch, batch)
        return RunOperations(operation_futures=[operation_future])

    def is_active(self) -> bool:
        return self._status == QueueStatus.ACTIVE

    def is_idle(self) -> bool:
        return self._status == QueueStatus.IDLE

    def _set_up_logging_thread(self) -> None:

View on GitHub (pinned to 6a27f2decc)

Solutions

  1. Call `queue.start()` before the first `log_batch_async` call.
  2. Prefer the managed MlflowClient async path so activation is handled automatically.
  3. If the queue was stopped, instantiate and start a fresh queue instead of reusing it.
  4. Check `queue.is_active()` before enqueueing and fall back to synchronous `log_batch` when inactive.

Example fix

# before
queue = AsyncLoggingQueue()
queue.log_batch_async(batch)

# after
queue = AsyncLoggingQueue()
queue.start()
queue.log_batch_async(batch)
Defensive patterns

Strategy: validation

Validate before calling

if not queue.is_active():
    queue.start()
queue.log_batch_async(run_id, metrics=metrics, params=params, tags=tags)

Type guard

def is_logging_queue_ready(queue) -> bool:
    return callable(getattr(queue, "is_active", None)) and queue.is_active()

Try / catch

from mlflow.exceptions import MlflowException
try:
    queue.log_batch_async(run_id, metrics=metrics, params=params, tags=tags)
except MlflowException as e:
    if "not activated" in str(e):
        queue.start()
        queue.log_batch_async(run_id, metrics=metrics, params=params, tags=tags)
    else:
        raise

Prevention

When it happens

Trigger: Calling `log_batch_async` on an AsyncLoggingQueue (e.g. AsyncBatchLoggingQueue used by MlflowClient for async logging) before `start()`, or after `stop()`/termination, or on a queue object whose worker thread died.

Common situations: Manually constructing an AsyncLoggingQueue without starting it; calling async logging after client teardown; sharing a queue across forked/pickled contexts where the thread doesn't survive; enabling async logging (MLFLOW_ENABLE_ASYNC_LOGGING) but terminating the run/flushing too early.

Related errors


AI-assisted analysis of mlflow/mlflow@6a27f2decc (2026-08-29). Data as JSON: /api/errors/36d7f5126c6e18ec. Report an issue: GitHub.