Skip to content

The validate modifier should also catch all exceptions. #635

Description

@Jadarma

The documentation on handling errors says:

convert and the other parameter transformations will wrap exceptions thrown inside them in a UsageError, so if you define a custom transformation, you don’t have to worry about an exception escaping to the user.

Since validate is not technically a transformation, the documentation does not lie, but the usage is unintuitive.
I foolishly assumed the require function is the same as the Kotlin stdlib, however it is an overload in the context of the OptionValidator.
I have some type that requires some more complex validator that is too big to fit nicely in the option declaration site, so it is extracted in a separate function:

val foo by option("--foo").validate { customValidationLogic(it) }

However, when validation fails here, since the custom logic does not throw BadParameterValue, it crashes the program assuming it's a programming error.

As a workaround for the time being, one must either do validation logic inside a convert lambda, or manually wrap exceptions, I defined my own util for this:

inline fun <AllT, EachT, ValueT> OptionWithValues<AllT, EachT, ValueT>.validateCatching(
    crossinline validator: OptionValidator<AllT & Any>,
): OptionDelegate<AllT> = copy(
    transformValue,
    transformEach,
    transformAll,
    validator = {
        if (it != null) runCatching { validator(it) }.getOrElse { cause ->
            throw BadParameterValue(cause.message.orEmpty(), option)
        }
    },
)

I believe the .validate {} lambda should match the behavior of the other transformers, to make it easier to use validation logic from functions that might come from external libraries, for example.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions