NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules
Go modules, #543 by repository stars
Latest stable
v4.5.0
Last release 18 days ago
27 Oct 2026
Ships unpredictably
gaps range from 8 days to 5.8 years
Most releases are documented
notes for 8 of 9 stable releases
Nothing withdrawn
no release was ever pulled
7 years old
23 releases · first in 2020
Drag across the ruler to compare, or tap a release to open it.
…on the latest release by design so that the vulnerability data is current. One required check, "Test", gates all jobs.
This release restores the v4.3.0 behavior that v4.4.0 changed for empty values. It adds explicit opt-ins for the
cases v4.4.0 was meant to fix, and fixes the problems found in the unreleased changes before they ship.
Restore the v4.3.0 empty-value semantics (#234, reported
by @ldez). Two "Breaking Changes" of v4.4.0 are reverted:
time.Time is. This applies to every rule that checks forRequired and NilOrNotEmpty pass again for a zero struct, and Required on a zeroValidatable struct reports the struct's own field errors instead of "cannot be blank". Empty reports a zeroIn, NotIn, Length, RuneLength, Dateis.*) validate a zero struct again. Each(Required) passes again forMin()/Max() skip empty values again (0, 0.0, the zero time.Time), as their documentation says.To keep the v4.4 checks, use the new opt-ins below.
Errors.Error() no longer starts with "; " when the first sorted key holds a nil error. An Errors with only
nil entries returns "", as an empty Errors does.
is.Latitude/is.Longitude are validation.StringRule again, as in v4.4.1, so code that holds them as a
StringRule compiles. String input is validated exactly as in v4.4.1: "NaN", "1e1", "0x1p-2", "45." and
".5" are rejected. Numbers are accepted as introduced by
#223; NaN and infinities are rejected.
A missing map key never runs its rules with a nil value: rules written for the key's type, such as a By with a
type assertion, no longer panic. The error stays "required key is missing" (validation_key_missing). Only a
Required or NotNil rule with a custom message (Error/ErrorObject) reports its own error
(#222 by
@nguyenvantuan2391996, narrowed) — fixes
#134.
EnsureString(nil) returns an error instead of panicking
(#232 by @yuefdev) — fixes
#233.
MultipleOf(0) returns an error instead of panicking with a division by zero
(#231 by @SashaMIT);
MultipleOf(nil) returns an error instead of panicking.
NotIn() compares with reflect.DeepEqual, as In() does: it no longer panics on uncomparable values such as
[]byte, and structs with pointer fields compare by the pointed-to values
(#229 by @youdie006).
ozzo_validation_no_template build tag: error messages are rendered without text/template, which removes it
from the binary and makes it noticeably smaller. Built-in messages read the same; custom messages support only
field placeholders such as {{.min}} and {{ .min }}. See the README
(#235 by @ldez) — fixes
#230.
ThresholdRule.ValidateEmpty(): Min/Max also check empty values, e.g. Min(0).Exclusive().ValidateEmpty()
rejects 0 (#165,
#180).
EmptyChecker interface: a struct type defines when its value is empty
(#143).
StringRule.AllowNumber(): a string rule can also accept finite numbers.
is.Latitude/is.Longitude accept numbers (int, uint and float types)
(#223 by
@nguyenvantuan2391996) — fixes
#185.
DateRule.Location(): parse dates that carry no time zone in a given location; the default stays UTC
(#220 by
@nguyenvantuan2391996) — fixes
#166.
Errors.Is: errors.Is finds a matching error anywhere in validation.Errors, including nested maps, slices and
structs (#225 by
@ChrisJr404) — fixes #116.
#225 also proposed Errors.As. It is not part of this release. With it, errors.As(err, &validation.Error)
returned the first field's error for a map of field errors, and code that uses that call to tell a single error from
a field map lost the field names. errors.As keeps reporting false for validation.Errors; use errors.Is or
Flatten() to reach the individual errors.
ErrorObject.Is: a validation error matches a built-in error with the same code, so
errors.Is(err, validation.ErrRequired) works, also for rules with a custom message such as
Required.Error("..."). Give the sentinel errors of your own rules a code: an error with an empty code never
matches.
Flatten(err), Errors.Flatten() and FieldError: a flat, sorted list of all field errors with the key path,
code, rendered message and params, and the error itself in Err. Field() gives items.0.name, Pointer() gives
the RFC 6901 pointer /items/0/name. Slice indexes sort numerically (items.2 before items.10). A single error
that is not an Errors is one entry with no path. Check Err for an InternalError before sending Message to a
client.
errors.Is and errors.As reach the error wrapped by NewInternalError.
README: "Empty Values", "Checking for an Error", "Listing Field Errors" and "Smaller Binaries" sections.
go 1.21 in go.mod), the minimum announced inis.CurrencyCode uses an ISO 4217 list maintained in this module instead of govalidator's, which adds currentozzo_validation_no_template tag. It also builds and tests on 386, checks formatting andgo mod tidy, and pins every tool version except govulncheck, which stays on the latest release by design so thatcoverage.out is removed; test outputs are ignored.go get github.com/go-ozzo/ozzo-validation/v4@v4.5.0Full changelog: v4.4.1...v4.5.0
Your coding agent can read these notes before it upgrades. Set up the MCP server →
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Struct field offset cache eliminates repeated reflect.StructField allocations.
Struct field offset cache eliminates repeated reflect.StructField allocations.
| Benchmark | v4.4.0 | v4.4.1 | Improvement |
|---|---|---|---|
| ValidateStruct (6 fields) | 59 allocs, 4.7 KB, 6.7µs | 38 allocs, 2.3 KB, 3.6µs | -36% allocs, -50% memory, -46% time |
| ValidateWithConditional | 34 allocs, 3.8µs | 19 allocs, 1.7µs | -44% allocs, -56% time |
Also fixes benchmark to pre-compile regex (was inflating alloc count).
Full Changelog: v4.4.0...v4.4.1
ValidateStruct with 6 fields makes 36% fewer allocations, uses 50% less memory and
runs 46% faster; ValidateWithConditional makes 44% fewer allocations and runs 56% faster.Revival release — ozzo-validation is actively maintained again after 6 years.
Revival release — ozzo-validation is actively maintained again after 6 years.
12 community PRs merged, maintainer bug fixes, modernized CI infrastructure.
is.UUIDv7 validation rule per RFC 9562 (#205 by @dmitryzhvinklis)is.ULID validation rule (#171 by @upamune)is.Origin validation rule for CORS origins (#198 by @nguyenvantuan2391996)OptionalKey() and DynamicMap() convenience constructors (#151 by @Jessinra)EachUntilFirstError() rule for large collections (#93 by @geekflyer)+ prefix per ITU-T standard (#208 by @Yanhu007)Each() now passes pointers correctly to By() callbacks (#160 by @dane)IsEmpty() treats all zero-valued structs as empty (#144 by @soranoba)Errors.Error() no longer panics on nil values (#212)Min()/Max() now validate zero values instead of silently skipping them (#212)These are bug fixes — the old behavior was incorrect:
is.E164 rejects phone numbers without + prefix (spec-correct)Each() with By() on pointer slices passes *T instead of TIsEmpty() returns true for zero-valued structs (was only time.Time{})Min()/Max() validate numeric zero and time.Time{} (were silently skipped)Thanks to all contributors who waited patiently — some PRs were open for 5+ years.
Special thanks to @qiangxue for entrusting the project to new maintainers.
Project revived after 6 years of inactivity. New maintainer: @kolkov.
is.UUIDv7 validation rule per RFC 9562 (#205 by @dmitryzhvinklis)is.ULID validation rule (#171 by @upamune)is.Origin validation rule for CORS origins (#198 by @nguyenvantuan2391996)OptionalKey() and DynamicMap() convenience constructors (#151 by @Jessinra)EachUntilFirstError() rule for large collections (#93 by @geekflyer)+ prefix per ITU-T standard (#208 by @Yanhu007) — fixes #195Each() now passes pointers correctly to By() callbacks (#160 by @dane)IsEmpty() treats all zero-valued structs as empty, not just time.Time{} (#144 by @soranoba) — fixes #143Errors.Error() no longer panics on nil values (#212) — fixes #147Min()/Max() now validate zero values instead of silently skipping them (#212) — fixes #165, #180is.E164 now rejects phone numbers without + prefix (spec-correct behavior)Each() with By() on pointer slices now passes *T instead of T (correct behavior)IsEmpty() returns true for zero-valued structs (was only time.Time{} before)Min()/Max() now validate numeric zero and time.Time{} instead of skipping themNothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Thanks to @NathanBaulch for the great contribution!
When and Each rulesThanks to @NathanBaulch for the great contribution!
#114 Fallback to field name for ignored JSON fields (thanks to @seriousben !) #123 Added Skip.When() to support conditional skipping validation rules
Skip.When() to support conditional skipping validation rules (thanks to @maratori!)Nothing published for this version
Nothing published for this version
Nothing published for this version
Upgraded govalidator to v10 and added the EmailFormat validation rule to validate an email address without checking the existence of MX record
EmailFormat validation rule to validate an email address without checking the existence of MX recordis.Domain rule. (thanks to @TheSecEng)Nil and Empty rules (thanks to @samber)Else clause to the When conditional validation construct (thanks to @samber)Length rule when requiring zero length (thanks to @0perl)RequiredRule struct is made public (thanks to @erdaltsksn)Nothing published for this version
#95 , #96 : Added validation.When() and validation.Required.When() to support conditional validation. Thanks to @mehran-prs for the great contribution
validation.When() and validation.Required.When() to support conditional validation. Thanks to @mehran-prs for the great contribution to this new feature!Improved the performance of Errors.Error() . Thanks to @geekflyer for the profiling work and code contribution!
validation.Error as the validation error type. It supports error code and parameter placeholders in error messages, which allows checking validation errors programmatically and translating error messages based on error codes. Thanks to @mehran-prs for the great contribution to this new feature!Errors.Error(). Thanks to @geekflyer for the profiling work and code contribution!Nothing published for this version
One column per quarter.