Skip to content

Verification

tessoir edited this page Mar 18, 2026 · 2 revisions

Verification

Verification<T> is a value bound to a ValidationScope. It is the primary surface for chaining validation rules and is created by calling verify on a scope:

validateCollecting {
    val verification: Verification<String> = verify(user::name)
}

In practice, you rarely hold a reference to it — rules are chained directly:

validateCollecting {
    verify(user::name).notBlank().minLength(3)
}

The scope property on Verification<T> carries the active ValidationContext, so any rules applied to it have access to path and other contextual information. The value property holds the value being validated.

Null-safe chaining

takeIfNotNull narrows a Verification<T?> to Verification<T> when the value is not null, returning null otherwise. This enables safe chaining of rules that expect a non-null type:

validateCollecting {
    verify(user::middleName)
        .takeIfNotNull()
        ?.minLength(2)
        ?.maxLength(50)
}

If middleName is null, the chain short-circuits and no rules are applied. If it is not null, the rules run normally on the unwrapped value.

Iterating iterables

each validates every element of an iterable, automatically appending each element's index to the validation path. It works on any Iterable<T> — collections being the most common case:

validateCollecting {
    verify(order::items).each { item ->
        verify(item::name).notBlank()
        verify(item::price).greaterThan(0.0)
    }
}

Each element is validated in its own indexed scope. If the third item fails, the violation path will reflect index 2.

each returns this, so you can chain further rules on the iterable itself after iterating its elements:

validateCollecting {
    verify(order::items)
        .minSize(1)
        .each { item ->
            verify(item::name).notBlank()
            verify(item::price).greaterThan(0.0)
        }
}

Writing rules

Rules in KVerify are extension functions on Verification<T>. The built-in rules are all defined this way, and your own rules follow the same pattern. This is covered in depth on the Rule page.

Next steps

  • Rule — learn how to write your own rules as extension functions and more

Clone this wiki locally