# Troubleshooting & FAQ (/integrations/celery/how-to/troubleshooting)



This guide collects the issues you are most likely to hit running Celery on KubeMQ, grouped by symptom: connection failures, tasks that do not execute or run twice, missing results, the "unknown transport" import error, and monitoring gaps. Each entry gives the cause and a concrete fix. For the underlying transport model see [Concepts](/integrations/celery/concepts); for every option referenced here see [Transport Options](/integrations/celery/reference/transport-options).

## Connection issues [#connection-issues]

<Accordions>
  <Accordion title="&#x22;Connection refused&#x22; on startup">
    **Symptom:** the worker fails to start with `KubeMQCeleryConnectionError: Failed to connect to KubeMQ broker`.

    **Cause:** the KubeMQ broker is not running or is not reachable at the configured address.

    ```bash
    # Verify the broker is running
    docker ps | grep kubemq
    ```

    If it is not running, start it:

    <RunKubeMQ ports="[50000, 9090]" />

    ```bash
    # Check connectivity (shared HTTP server on 9090, REST and the /health probe)
    curl -s http://localhost:9090/health
    ```
  </Accordion>

  <Accordion title="&#x22;Authentication failed&#x22;">
    **Symptom:** `KubeMQAuthenticationError` on connection.

    **Cause:** an invalid or missing auth token.

    ```python
    # Option 1: token in the URL (password field)
    app.conf.broker_url = "kubemq://:my-token@kubemq.default.svc:50000"

    # Option 2: token in transport options
    app.conf.broker_transport_options = {"auth_token": "my-token"}
    ```

    Verify the token matches the KubeMQ broker configuration.
  </Accordion>

  <Accordion title="&#x22;TLS handshake failed&#x22;">
    **Symptom:** the connection fails with a TLS/SSL error.

    **Cause:** a certificate mismatch, an expired certificate, or the wrong CA.

    ```python
    app.conf.broker_url = "kubemq+tls://kubemq.default.svc:50000"
    app.conf.broker_transport_options = {
        "tls_cert_file": "/certs/client.pem",
        "tls_key_file": "/certs/client-key.pem",
        "tls_ca_file": "/certs/ca.pem",
    }
    ```

    Confirm the certificate files are readable and not expired:

    ```bash
    openssl x509 -in /certs/client.pem -noout -dates
    ```
  </Accordion>

  <Accordion title="&#x22;Connection lost during operation&#x22;">
    **Symptom:** intermittent `KubeMQStreamBrokenError` or `KubeMQConnectionError`.

    **Cause:** network instability, a broker restart, or a load-balancer timeout.

    ```python
    app.conf.broker_transport_options = {
        "grpc_keepalive_time": 30,          # ping every 30s
        "grpc_keepalive_timeout": 10,       # wait 10s for a response
        "grpc_permit_without_calls": True,
    }
    ```

    gRPC keepalive detects the stale connection; Celery's built-in `broker_connection_retry` re-establishes it. See the [Error Handling guide](/integrations/celery/how-to/error-handling#recovering-from-dropped-connections) for the full recovery flow.
  </Accordion>
</Accordions>

## Task issues [#task-issues]

<Accordions>
  <Accordion title="Tasks not executing">
    **Symptom:** tasks are dispatched but never picked up by a worker.

    **Cause:** a queue-name mismatch, the worker is not consuming the right queue, or the worker is not connected.

    ```bash
    # Check which queues the worker is consuming
    celery -A myapp inspect active_queues

    # Verify the task is registered
    celery -A myapp inspect registered

    # Check queue depth via the shared HTTP server: curl http://localhost:9090/queue/info
    ```
  </Accordion>

  <Accordion title="Tasks executing twice">
    **Symptom:** duplicate task execution.

    **Cause:** with `task_acks_late=True`, if the KubeMQ transaction timeout expires before the task completes, the message is redelivered.

    ```python
    # Option 1: use acks_early (default, recommended for most tasks)
    app.conf.task_acks_late = False

    # Option 2: if acks_late is required, make the task idempotent
    @app.task(acks_late=True, reject_on_worker_lost=True)
    def idempotent_task(item_id: str):
        if cache.get(f"processed:{item_id}"):
            return  # skip duplicate
        # ... process ...
        cache.set(f"processed:{item_id}", True, timeout=86400)
    ```

    With `acks_early` (the default), KubeMQ's native ack eliminates the visibility-timeout race that causes duplicates on Redis.
  </Accordion>

  <Accordion title="Task results not found">
    **Symptom:** `result.get()` raises a timeout or returns `None`.

    **Cause:** the result backend is not configured, the result expired, or the result channel was never created.

    ```python
    app.conf.result_backend = "kubemq://localhost:50000"
    app.conf.result_expires = 86400  # 24 hours (KubeMQ maximum)
    ```

    Results expire after `result_expires` seconds — fetch them before expiration. See [Result Backend](/integrations/celery/how-to/result-backend) for the full retrieval model.
  </Accordion>

  <Accordion title="Tasks stuck in queue">
    **Symptom:** queue depth keeps growing but workers are idle.

    **Cause:** the worker is processing a different queue, or it is stuck.

    ```bash
    # Check which queues the worker is consuming
    celery -A myapp inspect active_queues

    # Start a worker on a specific queue
    celery -A myapp worker -Q myqueue --loglevel=info

    # Purge a stuck queue (CAUTION: deletes all messages)
    celery -A myapp purge -Q myqueue
    ```
  </Accordion>
</Accordions>

## Configuration issues [#configuration-issues]

<Accordions>
  <Accordion title="&#x22;Unknown transport: kubemq&#x22;">
    **Symptom:** `ValueError: Unknown transport 'kubemq'`.

    **Cause:** the `kubemq_celery` package is not imported before Celery resolves the broker URL.

    ```python
    import kubemq_celery  # MUST run before Celery uses the broker URL
    from celery import Celery

    app = Celery("myapp", broker="kubemq://localhost:50000")
    ```

    The import registers the `kubemq://` URL scheme with Kombu's transport registry.
  </Accordion>

  <Accordion title="&#x22;No module named kubemq_celery&#x22;">
    **Symptom:** `ModuleNotFoundError` on import.

    **Cause:** the package is not installed in the active Python environment.

    ```bash
    pip install kubemq-celery   # or: uv add kubemq-celery

    # Verify
    python -c "import kubemq_celery; print(kubemq_celery.__version__)"
    ```
  </Accordion>
</Accordions>

## Performance issues [#performance-issues]

<Accordions>
  <Accordion title="Slow task dispatch">
    **Symptom:** high latency between `task.delay()` and a worker receiving the task.

    **Cause:** network latency, large payloads, or suboptimal batch settings.

    ```python
    app.conf.broker_transport_options = {
        "wait_timeout": 1,
        "max_batch_size": 10,
        # For large payloads, raise the gRPC message limits:
        "max_send_size": 8_388_608,     # 8 MB
        "max_receive_size": 8_388_608,  # 8 MB
    }
    ```
  </Accordion>

  <Accordion title="Worker consuming slowly">
    **Symptom:** queue depth grows faster than the worker can process.

    **Cause:** low concurrency, CPU-bound tasks blocking the worker, or a low batch size.

    ```python
    # Raise concurrency for I/O-bound tasks: celery -A myapp worker --concurrency=8
    app.conf.worker_prefetch_multiplier = 4   # 4x concurrency
    app.conf.broker_transport_options = {"max_batch_size": 20}
    ```

    See the [Performance guide](/integrations/celery/how-to/performance) for full tuning recommendations and workload profiles.
  </Accordion>
</Accordions>

## Monitoring issues [#monitoring-issues]

<Accordions>
  <Accordion title="Flower shows no workers">
    **Symptom:** the Flower dashboard is empty or shows workers as offline.

    **Cause:** Flower cannot reach the broker, or fanout events are not being delivered.

    ```bash
    # Start Flower with the correct broker URL
    celery -A myapp flower --broker=kubemq://localhost:50000

    # Enable worker events so the celeryev fanout is published
    celery -A myapp worker --loglevel=info -E
    ```

    Flower uses Celery's event system, which rides KubeMQ Events (PubSub) for fanout. See [Concepts](/integrations/celery/concepts#the-kombu-virtual-transport) for how pidbox and monitoring traffic map onto Events.
  </Accordion>

  <Accordion title="&#x22;celery inspect&#x22; times out">
    **Symptom:** `celery inspect ping` hangs or times out.

    **Cause:** the worker's pidbox (control channel) subscription is not active, or the broker is unreachable.

    ```bash
    # Check with an explicit timeout
    celery -A myapp inspect ping --timeout=10

    # Verify the broker is accessible
    curl -s http://localhost:9090/health

    # Restart the worker to re-establish the pidbox subscription
    celery -A myapp control shutdown
    celery -A myapp worker --loglevel=info
    ```
  </Accordion>
</Accordions>

## KubeMQ vs Redis — issue comparison [#kubemq-vs-redis--issue-comparison]

| Issue                    | Redis behavior                                | KubeMQ behavior                                                          |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------------------ |
| Message loss on restart  | Lost unless AOF/RDB persistence is configured | Persistent storage by default                                            |
| Duplicate task execution | Visibility-timeout race causes duplicates     | Native ack/nack (no duplicates with `acks_early`)                        |
| Worker connection drops  | Silent failure, manual recovery               | gRPC keepalive, auto-reconnect via Celery retry                          |
| DLQ for failed tasks     | Manual implementation                         | Native `max_receive_count` + `dead_letter_queue`                         |
| Delayed-task OOM         | Tasks held in worker memory (client polling)  | Server-side `delay_in_seconds` (zero worker memory)                      |
| Connection exhaustion    | 6–8 TCP connections per worker                | 2–3 gRPC connections (HTTP/2 multiplexed)                                |
| Queue-depth monitoring   | Custom scripts or Redis CLI                   | REST `/queue/info` on `9090` plus the Management API dashboard on `8080` |
| Broker failover          | Sentinel or Cluster mode required             | Kubernetes-native StatefulSet auto-clustering                            |

### When Redis may still be appropriate [#when-redis-may-still-be-appropriate]

* **Sub-millisecond latency** for small payloads (Redis is in-memory).
* **Existing Redis infrastructure** already deployed and managed.
* **Result retention beyond 24 hours** — KubeMQ caps expiration at `86400` seconds.
* **Native O(1) chord unlock** — KubeMQ uses a polling fallback (see [Canvas Workflows](/integrations/celery/how-to/canvas-workflows#chord-uses-the-polling-fallback-on-kubemq)).

## Related [#related]

<Cards>
  <Card title="Error Handling" href="/integrations/celery/how-to/error-handling" description="Retries, dead letter queues, acks modes, idempotency, and reconnection." />

  <Card title="Configuration" href="/integrations/celery/how-to/configuration" description="Broker URL, transport options, TLS/mTLS, and async transport." />

  <Card title="Concepts" href="/integrations/celery/concepts" description="How the transport maps Celery onto KubeMQ Queues and Events." />
</Cards>
