python/cpython · error · ArgumentError

invalid %(type)s value: %(value)r

Error message

invalid %(type)s value: %(value)r

What it means

In _get_value, argparse calls the action's type callable on the raw string; if the callable raises ArgumentTypeError its message is used directly, but if it raises TypeError or ValueError (the typical case for built-ins like int('abc')) argparse wraps it in ArgumentError formatted as 'invalid <typename> value: <raw>'. The type name is taken from the callable's __name__ or its repr.

Source

Thrown at Lib/argparse.py:2811

        type_func = self._registry_get('type', action.type, action.type)
        if not callable(type_func):
            raise TypeError(f'{type_func!r} is not callable')

        # convert the value to the appropriate type
        try:
            result = type_func(arg_string)

        # ArgumentTypeErrors indicate errors
        except ArgumentTypeError as err:
            msg = str(err)
            raise ArgumentError(action, msg)

        # TypeErrors or ValueErrors also indicate errors
        except (TypeError, ValueError):
            name = getattr(action.type, '__name__', repr(action.type))
            args = {'type': name, 'value': arg_string}
            msg = _('invalid %(type)s value: %(value)r')
            raise ArgumentError(action, msg % args)

        # return the converted value
        return result

    def _check_value(self, action, value):
        # converted value must be one of the choices (if specified)
        choices = action.choices
        if choices is None:
            return

        if isinstance(choices, str):
            choices = iter(choices)

        if value not in choices:
            args = {'value': str(value),
                    'choices': ', '.join(repr(str(choice)) for choice in action.choices)}
            msg = _('invalid choice: %(value)r (choose from %(choices)s)')

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass a value the type callable can convert (e.g. a valid integer for type=int).
  2. In custom type functions, catch conversion errors and raise argparse.ArgumentTypeError('clear message') so users see your text, not 'invalid ... value'.
  3. If the argument may legitimately be absent or empty, add nargs='?' plus a default so the converter is not called on junk.

Example fix

# before
def port(s):
    return int(s)  # 'abc' -> invalid int value: 'abc'
parser.add_argument('-p', type=port)

# after
def port(s):
    try:
        v = int(s)
    except ValueError:
        raise argparse.ArgumentTypeError(f'not a valid port: {s!r}')
    if not 0 < v < 65536:
        raise argparse.ArgumentTypeError(f'port out of range: {v}')
    return v
parser.add_argument('-p', type=port)
Defensive patterns

Strategy: try-catch

Validate before calling

def make_typed(converter, name):
    def typed(s):
        try:
            return converter(s)
        except (ValueError, TypeError):
            raise argparse.ArgumentTypeError(
                f'invalid {name} value: {s!r}')
    return typed

parser.add_argument('-n', type=make_typed(int, 'int'))

Try / catch

try:
    args = parser.parse_args(argv)
except argparse.ArgumentError as e:
    if 'invalid' in str(e) and 'value' in str(e):
        print('one or more values failed type conversion; check --help for formats')

Prevention

When it happens

Trigger: add_argument('-n', type=int) with input 'abc' (int raises ValueError); a type=lambda s: complex(s) receiving an empty string; passing type=open with a nonexistent path (OSError propagates uncaught — different failure); a custom converter whose internals raise TypeError instead of ArgumentTypeError.

Common situations: Free-text CLI input that must be numeric or a date; environment-variable-derived arguments holding garbage; custom type functions that let ValueError leak instead of raising argparse.ArgumentTypeError with a friendly message.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/3b7e14fb09cd8949. Report an issue: GitHub.