{"record":{"id":"c5f2f1a4fa49642e","repo":"RicoSuter/NSwag","slug":"the-command-class-is-missing-the-commandattribute-attribute","errorCode":null,"errorMessage":"The command class is missing the CommandAttribute attribute.","messagePattern":"The command class is missing the CommandAttribute attribute\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/NSwag.Commands/NConsole/CommandLineProcessor.cs","lineNumber":77,"sourceCode":"\n        /// <summary>Loads all commands from an assembly (command classes must have the CommandAttribute with a defined Name).</summary>\n        /// <param name=\"assembly\">The assembly.</param>\n        public void RegisterCommandsFromAssembly(Assembly assembly)\n        {\n            var commandTypes = assembly.ExportedTypes.ToDictionary(t => t, t => t.GetTypeInfo().GetCustomAttribute<CommandAttribute>());\n            foreach (var pair in commandTypes.Where(p => !string.IsNullOrEmpty(p.Value?.Name) && p.Key.GetTypeInfo().IsClass && !p.Key.GetTypeInfo().IsAbstract))\n                RegisterCommand(pair.Value.Name, pair.Key);\n        }\n\n        /// <summary>Adds a command.</summary>\n        /// <param name=\"commandType\">Type of the command.</param>\n        /// <exception cref=\"InvalidOperationException\">The command has already been added.</exception>\n        /// <exception cref=\"InvalidOperationException\">The command class is missing the CommandAttribute attribute.</exception>\n        public void RegisterCommand(Type commandType)\n        {\n            var commandAttribute = commandType.GetTypeInfo().GetCustomAttribute<CommandAttribute>();\n            if (commandAttribute == null)\n                throw new InvalidOperationException(\"The command class is missing the CommandAttribute attribute.\");\n\n            RegisterCommand(commandAttribute.Name, commandType);\n        }\n\n        /// <summary>Adds a command.</summary>\n        /// <param name=\"name\">The name of the command.</param>\n        /// <param name=\"commandType\">Type of the command.</param>\n        /// <exception cref=\"InvalidOperationException\">The command has already been added.</exception>\n        public void RegisterCommand(string name, Type commandType)\n        {\n            if (_commands.ContainsKey(name))\n                throw new InvalidOperationException(\"The command '\" + name + \"' has already been added.\");\n\n            _commands.Add(name.ToLowerInvariant(), commandType);\n        }\n\n        /// <summary>Processes the command in the given command line arguments.</summary>\n        /// <param name=\"args\">The arguments.</param>","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/RicoSuter/NSwag/blob/63daf8fcc3a25151b62eb4b326a1e8ea048a0d41/src/NSwag.Commands/NConsole/CommandLineProcessor.cs#L59-L95","documentation":"CommandLineProcessor.RegisterCommand(Type) requires the command type to be decorated with CommandAttribute, which supplies the command's CLI name. If GetCustomAttribute<CommandAttribute>() returns null it throws InvalidOperationException. The command cannot be registered without a name.","triggerScenarios":"Calling processor.RegisterCommand(typeof(MyCommand)) where MyCommand has no [Command(\"name\", ...)] attribute; dynamically registering types from an assembly where some command-like classes were never annotated.","commonSituations":"Writing a custom NConsole command and forgetting the CommandAttribute; refactoring that removed the attribute; auto-registering all ICommand types in an assembly and one lacks the annotation.","solutions":["Add the CommandAttribute to the command class with the desired CLI name.","Only register types you've verified carry CommandAttribute (filter before calling RegisterCommand).","If registering many types via reflection, skip types without the attribute instead of throwing."],"exampleFix":"// before\npublic class MyCommand : IConsoleCommand { ... }\nprocessor.RegisterCommand(typeof(MyCommand));\n\n// after\n[Command(\"mycommand\", \"Does something\")]\npublic class MyCommand : IConsoleCommand { ... }\nprocessor.RegisterCommand(typeof(MyCommand));","handlingStrategy":"validation","validationCode":"var candidates = assembly.GetTypes().Where(t => typeof(IConsoleCommand).IsAssignableFrom(t));\nvar bad = candidates.Where(t => t.GetCustomAttribute<CommandAttribute>() == null).ToList();\nif (bad.Any()) Console.Error.WriteLine($\"Missing CommandAttribute on: {string.Join(\", \", bad.Select(t => t.Name))}\");","typeGuard":null,"tryCatchPattern":"try { processor.RegisterCommand(commandType); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"missing the CommandAttribute\")) { Console.Error.WriteLine($\"{commandType.Name} needs [Command(\\\"name\\\")].\"); }","preventionTips":["Annotate every command class with [Command(...)] at creation time","Filter reflection-based registration on types carrying CommandAttribute","Add a test enumerating all commands to catch missing attributes early"],"tags":["attributes","cli","command-registration"],"backgroundTag":"missing-required-attribute","analyzedSha":"63daf8fcc3a25151b62eb4b326a1e8ea048a0d41","analyzedAt":"2026-09-14T11:38:15.205Z","contentChangedAt":"2026-09-14T11:38:15.205Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}