{"record":{"id":"d00984f4437be3e9","repo":"App-vNext/Polly","slug":"the-bulkhead-semaphore-and-queue-are-full-and-exec","errorCode":null,"errorMessage":"The bulkhead semaphore and queue are full and execution was rejected.","messagePattern":"The bulkhead semaphore and queue are full and execution was rejected\\.","errorType":"exception","errorClass":"BulkheadRejectedException","httpStatus":null,"severity":"error","filePath":"src/Polly/Bulkhead/BulkheadEngine.cs","lineNumber":18,"sourceCode":"﻿#nullable enable\n\nnamespace Polly.Bulkhead;\n\ninternal static class BulkheadEngine\n{\n    internal static TResult Implementation<TResult>(\n        Func<Context, CancellationToken, TResult> action,\n        Context context,\n        Action<Context> onBulkheadRejected,\n        SemaphoreSlim maxParallelizationSemaphore,\n        SemaphoreSlim maxQueuedActionsSemaphore,\n        CancellationToken cancellationToken)\n    {\n        if (!maxQueuedActionsSemaphore.Wait(TimeSpan.Zero, cancellationToken))\n        {\n            onBulkheadRejected(context);\n            throw new BulkheadRejectedException();\n        }\n\n        try\n        {\n            maxParallelizationSemaphore.Wait(cancellationToken);\n            try\n            {\n                return action(context, cancellationToken);\n            }\n            finally\n            {\n                SafeRelease(maxParallelizationSemaphore);\n            }\n        }\n        finally\n        {\n            SafeRelease(maxQueuedActionsSemaphore);\n        }","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Bulkhead/BulkheadEngine.cs#L1-L36","documentation":"Thrown as a BulkheadRejectedException when the bulkhead policy cannot admit a new execution because both the parallelization slots and the queue are saturated. The engine calls maxQueuedActionsSemaphore.Wait(TimeSpan.Zero, ...) — a non-blocking probe — and if no queue slot is immediately available, the onBulkheadRejected callback fires and the exception is thrown. This is an intentional flow-control mechanism, not a bug.","triggerScenarios":"Calling policy.Execute(...) or policy.ExecuteAsync(...) when in-flight concurrent executions already equal maxParallelization AND waiting requests already equal maxQueuingActions. The zero-timeout semaphore Wait returns false at BulkheadEngine.cs:18, triggering immediate rejection.","commonSituations":"Downstream service latency spike consuming all parallelization slots while requests pile up in the queue. Traffic burst exceeding maxParallelization + maxQueuingActions combined. Under-provisioned bulkhead limits chosen during development that do not match production load.","solutions":["Increase maxQueuingActions (and/or maxParallelization) in the Policy.Bulkhead(...) call to absorb larger bursts","Wrap the Execute call in a try/catch for BulkheadRejectedException and return a fallback or HTTP 503","Chain a retry-with-backoff policy in front of the bulkhead so rejected requests are re-attempted after a delay","Apply client-side rate limiting upstream so the queue never fills to capacity"],"exampleFix":"// before\nvar policy = Policy.Bulkhead(10, 5);\nvar result = policy.Execute(() => CallService()); // throws when queue full\n\n// after\nvar policy = Policy.Bulkhead(10, 20);\ntry\n{\n    var result = policy.Execute(() => CallService());\n}\ncatch (BulkheadRejectedException)\n{\n    return StatusCode(StatusCodes.Status503ServiceUnavailable, \"At capacity\");\n}","handlingStrategy":"try-catch","validationCode":"// Check bulkhead capacity before executing\nif (policy.BulkheadAvailableCount == 0 && policy.QueueAvailableCount == 0)\n{\n    // Bulkhead will reject — handle proactively\n    return fallbackResult;\n}\nvar result = policy.Execute(() => CallService());","typeGuard":"public static bool CanAdmitRequest(BulkheadPolicy policy)\n{\n    return policy.BulkheadAvailableCount > 0 || policy.QueueAvailableCount > 0;\n}","tryCatchPattern":"try\n{\n    var result = policy.Execute(() => CallService());\n}\ncatch (BulkheadRejectedException ex)\n{\n    logger.LogWarning(ex, \"Bulkhead rejected execution\");\n    return StatusCode(StatusCodes.Status503ServiceUnavailable, \"Service at capacity\");\n}","preventionTips":["Size maxParallelization and maxQueuingActions based on load testing under realistic traffic","Monitor BulkheadAvailableCount and QueueAvailableCount to detect saturation before rejection","Chain a retry-with-jitter policy so transient rejections self-heal","Consider a fallback policy to return a default value instead of propagating the exception"],"tags":["bulkhead","runtime","capacity","rejection","concurrency","flow-control"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}