SignalR/SignalR · error · InvalidOperationException

The queue is full.

Error message

The queue is full.

What it means

Thrown by ScaleoutStream.Send when UsingTaskQueue is true and _queue.Enqueue returns null, meaning the task queue has reached its maximum capacity. This is backpressure: the scaleout stream's send queue (bounded by configuration.MaxQueueLength) is full because messages are arriving faster than the backplane can acknowledge them. The stream cannot buffer any more messages and rejects the send.

Source

Thrown at src/Microsoft.AspNet.SignalR.Core/Messaging/ScaleoutStream.cs:116

                var context = new SendContext(this, send, state);

                if (_initializeDrainTask != null && !_initializeDrainTask.IsCompleted)
                {
                    // Wait on the draining of the queue before proceeding with the send
                    // NOTE: Calling .Wait() here is safe because the task wasn't created on an ASP.NET request thread
                    //       and thus has no captured sync context
                    _initializeDrainTask.Wait();
                }

                if (UsingTaskQueue)
                {
                    Task task = _queue.Enqueue(Send, context);

                    if (task == null)
                    {
                        // The task is null if the queue is full
                        throw new InvalidOperationException(Resources.Error_TaskQueueFull);
                    }

                    // Always observe the task in case the user doesn't handle it
                    return task.Catch(_trace);
                }

                return Send(context);
            }
        }

        public void SetError(Exception error)
        {
            Trace(TraceEventType.Error, "Error has happened with the following exception: {0}.", error);

            lock (_lockObj)
            {
                _perfCounters.ScaleoutErrorsTotal.Increment();
                _perfCounters.ScaleoutErrorsPerSec.Increment();

View on GitHub (pinned to 693053b89a)

Solutions

  1. Investigate backplane health — check Redis/SQL/Service Bus latency and capacity.
  2. Increase MaxQueueLength in ScaleoutConfiguration if the backplane can sustain higher catch-up load.
  3. Implement client-side throttling or message batching to reduce send rate.
  4. Consider a higher-throughput backplane (e.g., Redis over Service Bus).

Example fix

// before — default small queue
var config = new ScaleoutConfiguration() { MaxQueueLength = 50 };

// after — larger queue to absorb bursts
var config = new ScaleoutConfiguration() { MaxQueueLength = 1000 };
Defensive patterns

Strategy: retry

Try / catch

try {
    streamManager.Send(streamIndex, messages);
} catch (InvalidOperationException ex) when (ex.Message.Contains("queue is full")) {
    // Backpressure — back off and retry, or drop/throttle
    logger.Warn("Scaleout queue full, applying backpressure", ex);
    await Task.Delay(backoffDelay);
    // consider reducing send rate or increasing MaxQueueLength
}

Prevention

When it happens

Trigger: The scaleout backplane is slow or unresponsive, causing the send queue to fill up to MaxQueueLength. Each call to Send attempts _queue.Enqueue; when the queue is at capacity it returns null and the exception fires. Common during backplane outages or severe network latency.

Common situations: Redis/SQL/Service Bus backplane is down or slow; sudden message burst exceeding backplane throughput; MaxQueueLength configured too small for the load; network partition between app servers and backplane; the backplane connection is in a buffering state for too long.

Related errors


AI-assisted analysis of SignalR/SignalR@693053b89a (2026-08-13). Data as JSON: /api/errors/9c520e08e845e45e. Report an issue: GitHub.