{"record":{"id":"046bd1cd03cb6e9b","repo":"HangfireIO/Hangfire","slug":"current-storage-doesn-t-support-specifying-queues","errorCode":null,"errorMessage":"Current storage doesn't support specifying queues directly for a specific job. Please use the QueueAttribute instead.","messagePattern":"Current storage doesn't support specifying queues directly for a specific job\\. Please use the QueueAttribute instead\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.Core/Client/CoreBackgroundJobFactory.cs","lineNumber":63,"sourceCode":"        public int RetryAttempts\n        {\n            get { lock (_syncRoot) { return _retryAttempts; } }\n            set { lock (_syncRoot) { _retryAttempts = value; } }\n        }\n\n        public Func<int, TimeSpan> RetryDelayFunc\n        {\n            get { lock (_syncRoot) { return _retryDelayFunc; } }\n            set { lock (_syncRoot) { _retryDelayFunc = value; } }\n        }\n\n        public BackgroundJob Create(CreateContext context)\n        {\n            if (context == null) throw new ArgumentNullException(nameof(context));\n\n            if (context.Job.Queue != null && !context.Storage.HasFeature(JobStorageFeatures.JobQueueProperty))\n            {\n                throw new NotSupportedException(\"Current storage doesn't support specifying queues directly for a specific job. Please use the QueueAttribute instead.\");\n            }\n\n            var parameters = context.Parameters.ToDictionary(\n                static x => x.Key,\n                static x => SerializationHelper.Serialize(x.Value, SerializationOption.User));\n\n            var createdAt = DateTime.UtcNow;\n            var expireIn = TimeSpan.FromDays(30);\n\n            return CreateBackgroundJobTwoSteps(context, parameters, createdAt, expireIn);\n        }\n\n        private BackgroundJob CreateBackgroundJobTwoSteps(CreateContext context, Dictionary<string, string> parameters, DateTime createdAt, TimeSpan expireIn)\n        {\n            var attemptsLeft = Math.Max(RetryAttempts, 0);\n\n            // Retry may cause multiple background jobs to be created, especially when there's\n            // a timeout-related exception. But initialization attempt will be performed only","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.Core/Client/CoreBackgroundJobFactory.cs#L45-L81","documentation":"NotSupportedException thrown by CoreBackgroundJobFactory.Create when a job specifies a Queue (context.Job.Queue != null) but the configured JobStorage does not advertise the JobQueueProperty feature (checked via context.Storage.HasFeature(JobStorageFeatures.JobQueueProperty)). Per-job queue targeting via the Job constructor's queue parameter or the queue argument of FromExpression requires storage that understands queue assignment per job; otherwise the [Queue] attribute (a job filter that sets the queue at the state level) is the supported path.","triggerScenarios":"Calling Job.FromExpression(() => ..., queue: \"critical\") or new Job(type, method, args, \"critical\") against a storage (e.g., MemoryStorage in older versions, or a custom storage) that returns false for HasFeature(JobStorageFeatures.JobQueueProperty). Also triggered by BackgroundJob.Enqueue<T>(..., queue: ...) overloads when storage lacks the feature.","commonSituations":"Using MemoryStorage or a minimal storage implementation in development that does not implement per-job queue support; upgrading Hangfire and using the new per-job queue API against an older storage package; custom JobStorage implementations that do not declare JobQueueProperty.","solutions":["Use the [Queue(\"critical\")] attribute on the job method/class instead of the queue parameter — it sets the queue through the EnqueuedState and is universally supported.","Switch to a storage that supports per-job queues (e.g., SqlServer, Redis with a current package) which advertises JobQueueProperty.","If you maintain a custom JobStorage, override HasFeature to return true for JobQueueProperty and implement queue-aware job creation."],"exampleFix":"// before — requires JobQueueProperty support\nBackgroundJob.Enqueue<MyService>(x => x.DoWork(), \"critical\");\n\n// after — works with any storage\n[Queue(\"critical\")]\npublic class MyService { public void DoWork() { ... } }\n// or on the method:\npublic class MyService {\n    [Queue(\"critical\")]\n    public void DoWork() { ... }\n}","handlingStrategy":"validation","validationCode":"var supportsPerJobQueue = JobStorage.Current.HasFeature(JobStorageFeatures.JobQueueProperty);\nif (!supportsPerJobQueue && !string.IsNullOrEmpty(queueName))\n    throw new InvalidOperationException(\"Storage does not support per-job queues; use [Queue] attribute instead.\");\n// then enqueue normally or via attribute","typeGuard":"public static bool StorageSupportsPerJobQueue(JobStorage storage)\n    => storage != null && storage.HasFeature(JobStorageFeatures.JobQueueProperty);","tryCatchPattern":"try { BackgroundJob.Enqueue<T>(x => x.DoWork(), \"critical\"); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"queues directly\"))\n{ /* fall back to [Queue] attribute-based enqueue */ }","preventionTips":["Default to the [Queue(\"name\")] attribute for queue routing — it works with all storages.","Before using the per-job queue parameter, check JobStorage.Current.HasFeature(JobStorageFeatures.JobQueueProperty).","Keep storage packages updated so feature support matches the Core version you target."],"tags":["not-supported","queues","storage-features","configuration"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}