diff --git a/src/click/termui.py b/src/click/termui.py index 2e98a0771..1f0edb9c8 100644 --- a/src/click/termui.py +++ b/src/click/termui.py @@ -177,10 +177,7 @@ def prompt_func(text: str) -> str: try: result = value_proc(value) except UsageError as e: - if hide_input: - echo(_("Error: The value you entered was invalid."), err=err) - else: - echo(_("Error: {e.message}").format(e=e), err=err) + echo(_("Error: {e.message}").format(e=e), err=err) continue if not confirmation_prompt: return result diff --git a/tests/test_utils.py b/tests/test_utils.py index 1b1575657..a6f0357b1 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -746,3 +746,30 @@ def test_make_default_short_help(value, max_length, alter, expect): out = click.utils.make_default_short_help(value, max_length) assert out == expect + + +def test_hide_input_shows_custom_error(runner): + """With hide_input=True, custom error messages from type validation + should still be displayed, not swallowed by a generic message.""" + + class StrictPassword(click.ParamType): + name = "password" + + def convert(self, value, param, ctx): + if len(value) < 8: + self.fail("Password must be at least 8 characters", param, ctx) + return value + + @click.command() + @click.option( + "--pw", + prompt=True, + hide_input=True, + type=StrictPassword(), + ) + def cmd(pw): + click.echo(f"OK:{pw}") + + result = runner.invoke(cmd, input="short\nlong_enough_pw\n") + assert "Password must be at least 8 characters" in result.output + assert "OK:long_enough_pw" in result.output