{"record":{"id":"a7a57563e7b60ae5","repo":"HangfireIO/Hangfire","slug":"featureid-a7a575","errorCode":null,"errorMessage":"featureId","messagePattern":"featureId","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Hangfire.SqlServer/SqlServerStorage.cs","lineNumber":201,"sourceCode":"        public override IEnumerable<IBackgroundProcess> GetServerRequiredProcesses()\n        {\n            yield return _heartbeatProcess;\n        }\n\n        public override IEnumerable<IBackgroundProcess> GetStorageWideProcesses()\n        {\n            yield return new ExpirationManager(this, _options.InactiveStateExpirationTimeout, _options.JobExpirationCheckInterval);\n            yield return new CountersAggregator(this, _options.CountersAggregateInterval);\n        }\n\n        public override void WriteOptionsToLog(ILog logger)\n        {\n            logger.Info($\"Using the following options for SQL Server job storage: Queue poll interval: {_options.QueuePollInterval}.\");\n        }\n\n        public override bool HasFeature(string featureId)\n        {\n            if (featureId == null) throw new ArgumentNullException(nameof(featureId));\n\n            return _features.TryGetValue(featureId, out var isSupported) \n                ? isSupported\n                : base.HasFeature(featureId);\n        }\n\n        public override string ToString()\n        {\n            const string canNotParseMessage = \"<Connection string can not be parsed>\";\n\n            try\n            {\n                if (_connectionString == null)\n                {\n                    return \"SQL Server (custom)\";\n                }\n\n                var parts = _connectionString.Split(SemicolonSeparator, StringSplitOptions.RemoveEmptyEntries)","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/HangfireIO/Hangfire/blob/c236dd0f930f831ec151e436e138ddc429a02a72/src/Hangfire.SqlServer/SqlServerStorage.cs#L183-L219","documentation":"The HasFeature method received a null featureId argument. This is a standard ArgumentNullException guard; the method looks up the feature ID string in an internal dictionary (_features) before delegating to the base implementation.","triggerScenarios":"Calling storage.HasFeature(null); passing a feature identifier variable that was never assigned or came from a null config value.","commonSituations":"Programmatic feature checks with uninitialized strings; feature-gating logic that receives null from an upstream source.","solutions":["Pass a non-null feature identifier string such as \"Job.Queue\" or \"Transaction.\".","Validate the feature ID before calling HasFeature if the source may be null.","Use known Hangfire feature constant strings."],"exampleFix":"// before\nvar supported = storage.HasFeature(featureName); // featureName is null\n// after\nvar supported = !string.IsNullOrEmpty(featureName) && storage.HasFeature(featureName);","handlingStrategy":"validation","validationCode":"string featureId = /* from logic or config */;\nif (string.IsNullOrEmpty(featureId))\n    return false; // or throw, depending on your logic\n\nbool supported = storage.HasFeature(featureId);","typeGuard":"static bool IsQueryableFeature(string featureId) => !string.IsNullOrEmpty(featureId);","tryCatchPattern":null,"preventionTips":["Guard against null/empty feature IDs before calling HasFeature.","Use well-known Hangfire feature string constants when available."],"tags":["argument-null","has-feature","validation"],"backgroundTag":null,"analyzedSha":"c236dd0f930f831ec151e436e138ddc429a02a72","analyzedAt":"2026-08-13T20:27:11.027Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}