clap_builder/error/
kind.rs

1/// Command line argument parser kind of error
2#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
3#[non_exhaustive]
4pub enum ErrorKind {
5    /// Occurs when an [`Arg`][crate::Arg] has a set of possible values,
6    /// and the user provides a value which isn't in that set.
7    ///
8    /// # Examples
9    ///
10    /// ```rust
11    /// # use clap_builder as clap;
12    /// # use clap::{Command, Arg, error::ErrorKind};
13    /// let result = Command::new("prog")
14    ///     .arg(Arg::new("speed")
15    ///         .value_parser(["fast", "slow"]))
16    ///     .try_get_matches_from(vec!["prog", "other"]);
17    /// assert!(result.is_err());
18    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidValue);
19    /// ```
20    InvalidValue,
21
22    /// Occurs when a user provides a flag, option, argument or subcommand which isn't defined.
23    ///
24    /// # Examples
25    ///
26    /// ```rust
27    /// # use clap_builder as clap;
28    /// # use clap::{Command, arg, error::ErrorKind};
29    /// let result = Command::new("prog")
30    ///     .arg(arg!(--flag "some flag"))
31    ///     .try_get_matches_from(vec!["prog", "--other"]);
32    /// assert!(result.is_err());
33    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::UnknownArgument);
34    /// ```
35    UnknownArgument,
36
37    /// Occurs when the user provides an unrecognized [`Subcommand`] which meets the threshold for
38    /// being similar enough to an existing subcommand.
39    /// If it doesn't meet the threshold, or the 'suggestions' feature is disabled,
40    /// the more general [`UnknownArgument`] error is returned.
41    ///
42    /// # Examples
43    ///
44    /// ```rust
45    /// # #[cfg(feature = "suggestions")] {
46    /// # use clap_builder as clap;
47    /// # use clap::{Command, Arg, error::ErrorKind, };
48    /// let result = Command::new("prog")
49    ///     .subcommand(Command::new("config")
50    ///         .about("Used for configuration")
51    ///         .arg(Arg::new("config_file")
52    ///             .help("The configuration file to use")))
53    ///     .try_get_matches_from(vec!["prog", "confi"]);
54    /// assert!(result.is_err());
55    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidSubcommand);
56    /// # }
57    /// ```
58    ///
59    /// [`Subcommand`]: crate::Subcommand
60    /// [`UnknownArgument`]: ErrorKind::UnknownArgument
61    InvalidSubcommand,
62
63    /// Occurs when the user doesn't use equals for an option that requires equal
64    /// sign to provide values.
65    ///
66    /// ```rust
67    /// # use clap_builder as clap;
68    /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
69    /// let res = Command::new("prog")
70    ///     .arg(Arg::new("color")
71    ///          .action(ArgAction::Set)
72    ///          .require_equals(true)
73    ///          .long("color"))
74    ///     .try_get_matches_from(vec!["prog", "--color", "red"]);
75    /// assert!(res.is_err());
76    /// assert_eq!(res.unwrap_err().kind(), ErrorKind::NoEquals);
77    /// ```
78    NoEquals,
79
80    /// Occurs when the user provides a value for an argument with a custom validation and the
81    /// value fails that validation.
82    ///
83    /// # Examples
84    ///
85    /// ```rust
86    /// # use clap_builder as clap;
87    /// # use clap::{Command, Arg, error::ErrorKind, value_parser};
88    /// fn is_numeric(val: &str) -> Result<(), String> {
89    ///     match val.parse::<i64>() {
90    ///         Ok(..) => Ok(()),
91    ///         Err(..) => Err(String::from("value wasn't a number!")),
92    ///     }
93    /// }
94    ///
95    /// let result = Command::new("prog")
96    ///     .arg(Arg::new("num")
97    ///          .value_parser(value_parser!(u8)))
98    ///     .try_get_matches_from(vec!["prog", "NotANumber"]);
99    /// assert!(result.is_err());
100    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ValueValidation);
101    /// ```
102    ValueValidation,
103
104    /// Occurs when a user provides more values for an argument than were defined by setting
105    /// [`Arg::num_args`].
106    ///
107    /// # Examples
108    ///
109    /// ```rust
110    /// # use clap_builder as clap;
111    /// # use clap::{Command, Arg, error::ErrorKind};
112    /// let result = Command::new("prog")
113    ///     .arg(Arg::new("arg")
114    ///         .num_args(1..=2))
115    ///     .try_get_matches_from(vec!["prog", "too", "many", "values"]);
116    /// assert!(result.is_err());
117    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooManyValues);
118    /// ```
119    /// [`Arg::num_args`]: crate::Arg::num_args()
120    TooManyValues,
121
122    /// Occurs when the user provides fewer values for an argument than were defined by setting
123    /// [`Arg::num_args`].
124    ///
125    /// # Examples
126    ///
127    /// ```rust
128    /// # use clap_builder as clap;
129    /// # use clap::{Command, Arg, error::ErrorKind};
130    /// let result = Command::new("prog")
131    ///     .arg(Arg::new("some_opt")
132    ///         .long("opt")
133    ///         .num_args(3..))
134    ///     .try_get_matches_from(vec!["prog", "--opt", "too", "few"]);
135    /// assert!(result.is_err());
136    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::TooFewValues);
137    /// ```
138    /// [`Arg::num_args`]: crate::Arg::num_args()
139    TooFewValues,
140
141    /// Occurs when the user provides a different number of values for an argument than what's
142    /// been defined by setting [`Arg::num_args`] or than was implicitly set by
143    /// [`Arg::value_names`].
144    ///
145    /// # Examples
146    ///
147    /// ```rust
148    /// # use clap_builder as clap;
149    /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
150    /// let result = Command::new("prog")
151    ///     .arg(Arg::new("some_opt")
152    ///         .long("opt")
153    ///         .action(ArgAction::Set)
154    ///         .num_args(2))
155    ///     .try_get_matches_from(vec!["prog", "--opt", "wrong"]);
156    /// assert!(result.is_err());
157    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
158    /// ```
159    ///
160    /// [`Arg::num_args`]: crate::Arg::num_args()
161    /// [`Arg::value_names`]: crate::Arg::value_names()
162    WrongNumberOfValues,
163
164    /// Occurs when the user provides two values which conflict with each other and can't be used
165    /// together.
166    ///
167    /// # Examples
168    ///
169    /// ```rust
170    /// # use clap_builder as clap;
171    /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
172    /// let result = Command::new("prog")
173    ///     .arg(Arg::new("debug")
174    ///         .long("debug")
175    ///         .action(ArgAction::SetTrue)
176    ///         .conflicts_with("color"))
177    ///     .arg(Arg::new("color")
178    ///         .long("color")
179    ///         .action(ArgAction::SetTrue))
180    ///     .try_get_matches_from(vec!["prog", "--debug", "--color"]);
181    /// assert!(result.is_err());
182    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::ArgumentConflict);
183    /// ```
184    ArgumentConflict,
185
186    /// Occurs when the user does not provide one or more required arguments.
187    ///
188    /// # Examples
189    ///
190    /// ```rust
191    /// # use clap_builder as clap;
192    /// # use clap::{Command, Arg, error::ErrorKind};
193    /// let result = Command::new("prog")
194    ///     .arg(Arg::new("debug")
195    ///         .required(true))
196    ///     .try_get_matches_from(vec!["prog"]);
197    /// assert!(result.is_err());
198    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
199    /// ```
200    MissingRequiredArgument,
201
202    /// Occurs when a subcommand is required (as defined by [`Command::subcommand_required`]),
203    /// but the user does not provide one.
204    ///
205    /// # Examples
206    ///
207    /// ```rust
208    /// # use clap_builder as clap;
209    /// # use clap::{Command, error::ErrorKind};
210    /// let err = Command::new("prog")
211    ///     .subcommand_required(true)
212    ///     .subcommand(Command::new("test"))
213    ///     .try_get_matches_from(vec![
214    ///         "myprog",
215    ///     ]);
216    /// assert!(err.is_err());
217    /// assert_eq!(err.unwrap_err().kind(), ErrorKind::MissingSubcommand);
218    /// # ;
219    /// ```
220    ///
221    /// [`Command::subcommand_required`]: crate::Command::subcommand_required
222    MissingSubcommand,
223
224    /// Occurs when the user provides a value containing invalid UTF-8.
225    ///
226    /// To allow arbitrary data
227    /// - Set [`Arg::value_parser(value_parser!(OsString))`] for argument values
228    /// - Set [`Command::external_subcommand_value_parser`] for external-subcommand
229    ///   values
230    ///
231    /// # Platform Specific
232    ///
233    /// Non-Windows platforms only (such as Linux, Unix, OSX, etc.)
234    ///
235    /// # Examples
236    ///
237    /// ```rust
238    /// # #[cfg(unix)] {
239    /// # use clap_builder as clap;
240    /// # use clap::{Command, Arg, error::ErrorKind, ArgAction};
241    /// # use std::os::unix::ffi::OsStringExt;
242    /// # use std::ffi::OsString;
243    /// let result = Command::new("prog")
244    ///     .arg(Arg::new("utf8")
245    ///         .short('u')
246    ///         .action(ArgAction::Set))
247    ///     .try_get_matches_from(vec![OsString::from("myprog"),
248    ///                                 OsString::from("-u"),
249    ///                                 OsString::from_vec(vec![0xE9])]);
250    /// assert!(result.is_err());
251    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::InvalidUtf8);
252    /// # }
253    /// ```
254    ///
255    /// [`Arg::allow_invalid_utf8`]: crate::Arg::allow_invalid_utf8
256    /// [`Command::external_subcommand_value_parser`]: crate::Command::external_subcommand_value_parser
257    InvalidUtf8,
258
259    /// Not a true "error" as it means `--help` or similar was used.
260    /// The help message will be sent to `stdout`.
261    ///
262    /// **Note**: If the help is displayed due to an error (such as missing subcommands) it will
263    /// be sent to `stderr` instead of `stdout`.
264    ///
265    /// # Examples
266    ///
267    /// ```rust
268    /// # #[cfg(feature = "help")] {
269    /// # use clap_builder as clap;
270    /// # use clap::{Command, Arg, error::ErrorKind};
271    /// let result = Command::new("prog")
272    ///     .try_get_matches_from(vec!["prog", "--help"]);
273    /// assert!(result.is_err());
274    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelp);
275    /// # }
276    /// ```
277    DisplayHelp,
278
279    /// Occurs when either an argument or a [`Subcommand`] is required, as defined by
280    /// [`Command::arg_required_else_help`] , but the user did not provide
281    /// one.
282    ///
283    /// # Examples
284    ///
285    /// ```rust
286    /// # use clap_builder as clap;
287    /// # use clap::{Command, Arg, error::ErrorKind, };
288    /// let result = Command::new("prog")
289    ///     .arg_required_else_help(true)
290    ///     .subcommand(Command::new("config")
291    ///         .about("Used for configuration")
292    ///         .arg(Arg::new("config_file")
293    ///             .help("The configuration file to use")))
294    ///     .try_get_matches_from(vec!["prog"]);
295    /// assert!(result.is_err());
296    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand);
297    /// ```
298    ///
299    /// [`Subcommand`]: crate::Subcommand
300    /// [`Command::arg_required_else_help`]: crate::Command::arg_required_else_help
301    DisplayHelpOnMissingArgumentOrSubcommand,
302
303    /// Not a true "error" as it means `--version` or similar was used.
304    /// The message will be sent to `stdout`.
305    ///
306    /// # Examples
307    ///
308    /// ```rust
309    /// # use clap_builder as clap;
310    /// # use clap::{Command, Arg, error::ErrorKind};
311    /// let result = Command::new("prog")
312    ///     .version("3.0")
313    ///     .try_get_matches_from(vec!["prog", "--version"]);
314    /// assert!(result.is_err());
315    /// assert_eq!(result.unwrap_err().kind(), ErrorKind::DisplayVersion);
316    /// ```
317    DisplayVersion,
318
319    /// Represents an [I/O error].
320    /// Can occur when writing to `stderr` or `stdout` or reading a configuration file.
321    ///
322    /// [I/O error]: std::io::Error
323    Io,
324
325    /// Represents a [Format error] (which is a part of [`Display`]).
326    /// Typically caused by writing to `stderr` or `stdout`.
327    ///
328    /// [`Display`]: std::fmt::Display
329    /// [Format error]: std::fmt::Error
330    Format,
331}
332
333impl ErrorKind {
334    /// End-user description of the error case, where relevant
335    pub fn as_str(self) -> Option<&'static str> {
336        match self {
337            Self::InvalidValue => Some("one of the values isn't valid for an argument"),
338            Self::UnknownArgument => Some("unexpected argument found"),
339            Self::InvalidSubcommand => Some("unrecognized subcommand"),
340            Self::NoEquals => Some("equal is needed when assigning values to one of the arguments"),
341            Self::ValueValidation => Some("invalid value for one of the arguments"),
342            Self::TooManyValues => Some("unexpected value for an argument found"),
343            Self::TooFewValues => Some("more values required for an argument"),
344            Self::WrongNumberOfValues => Some("too many or too few values for an argument"),
345            Self::ArgumentConflict => {
346                Some("an argument cannot be used with one or more of the other specified arguments")
347            }
348            Self::MissingRequiredArgument => {
349                Some("one or more required arguments were not provided")
350            }
351            Self::MissingSubcommand => Some("a subcommand is required but one was not provided"),
352            Self::InvalidUtf8 => Some("invalid UTF-8 was detected in one or more arguments"),
353            Self::DisplayHelp => None,
354            Self::DisplayHelpOnMissingArgumentOrSubcommand => None,
355            Self::DisplayVersion => None,
356            Self::Io => None,
357            Self::Format => None,
358        }
359    }
360}
361
362impl std::fmt::Display for ErrorKind {
363    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
364        self.as_str().unwrap_or_default().fmt(f)
365    }
366}