Class ValidationCodes
- Namespace
- Trellis
- Assembly
- Trellis.Core.dll
The closed set of machine-readable reason codes Trellis itself emits.
public static class ValidationCodes
- Inheritance
-
ValidationCodes
- Inherited Members
Remarks
A reason code is the stable, localizable identity of a failure. ReasonCode
and ReasonCode carry it to the wire, where a client uses it to look up
its own prose rather than parsing the English in Detail. That is only worth doing if the same
logical failure always arrives under the same code, which is why this set is closed and why it is
declared in one place instead of spelled inline at each producer.
This vocabulary is frozen. Codes may be added in later releases; an existing code is never
repointed at a different meaning and never silently renamed, because a client's catalog keys on it.
A code absent from a client's catalog degrades through namespace fallback — a client that does not
know string.exact-length can still fall back on string — so adding is safe in a way
that redefining is not.
The freeze constrains Trellis, not the application. An application is free to emit any code it
likes: FluentValidation's WithErrorCode passes through verbatim, and a domain type can hand
any string to Error.InvalidInput. Nothing here is validated against application codes.
Namespace boundaries decide which code a new producer should reach for, and exist because ~210 producer sites would otherwise each answer the question differently:
format.* |
Lexical failures only — a CLR scalar could not be constructed from the text. This includes
out-of-range-for-type: "99999999999" into an int is
FormatInteger, not NumberOverflow, because no integer was ever built.
|
string.* | A string arrived intact but did not match an expected shape. All ISO code sets live here. |
number.* | Validation of an already-parsed number. NumberOverflow is arithmetic only, never a parse. NumberPrecision is a parsed decimal exceeding scale or precision — malformed input is FormatDecimal. |
value.* | Type-agnostic presence and comparison. |
fields.* |
The subject is a set of fields rather than one — the cross-field invariants in
MaybeInvariant. Accurate whichever wire member ends up carrying the violation.
|
enum.*, money.*, schedule.* | Domain-specific. |
One code per meaning, regardless of which producer noticed it. A malformed integer is
FormatInteger whether it arrived through query-string binding, a JSON body, or a
generated TryCreate — a client cannot be asked to know which pipeline ran.
Fields
AttributeInvalid
An actor attribute was not valid.
public const string AttributeInvalid = "attribute.invalid"
Field Value
CursorMalformed
A pagination cursor could not be decoded.
public const string CursorMalformed = "cursor.malformed"
Field Value
EnumNameUndefined
A symbolic name does not correspond to any member. Distinct from EnumUndefined, which is about a numeric value that parsed.
public const string EnumNameUndefined = "enum.name-undefined"
Field Value
EnumUndefined
A value parsed as the enum's underlying type but is not a defined member.
public const string EnumUndefined = "enum.undefined"
Field Value
EtagMalformed
An ETag header value could not be parsed. Named to match CursorMalformed — the same failure class, described the same way.
public const string EtagMalformed = "etag.malformed"
Field Value
FieldsAllOrNone
Some but not all of a group were provided, when the group is all-or-nothing.
public const string FieldsAllOrNone = "fields.all-or-none"
Field Value
FieldsAtLeastOne
None of a group was provided, when at least one is required.
public const string FieldsAtLeastOne = "fields.at-least-one"
Field Value
FieldsExactlyOne
None of a group was provided, when exactly one is required.
public const string FieldsExactlyOne = "fields.exactly-one"
Field Value
FieldsMutuallyExclusive
More than one of a mutually exclusive group was provided.
public const string FieldsMutuallyExclusive = "fields.mutually-exclusive"
Field Value
FieldsOnlyOne
More than one of a group was provided, when exactly one is required. Distinct from FieldsExactlyOne so a client can say "you must choose one" and "you may not choose both" differently.
public const string FieldsOnlyOne = "fields.only-one"
Field Value
FieldsRequiredWith
A field was provided that requires another field which was not.
public const string FieldsRequiredWith = "fields.required-with"
Field Value
FormatBoolean
Not a valid boolean.
public const string FormatBoolean = "format.boolean"
Field Value
FormatConversion
The text could not be converted to the target type, and no more specific code applies — including a JSON token of the wrong type.
public const string FormatConversion = "format.conversion"
Field Value
FormatDate
Not a valid date.
public const string FormatDate = "format.date"
Field Value
FormatDateTime
Not a valid date and time.
public const string FormatDateTime = "format.date-time"
Field Value
FormatDecimal
Not a valid decimal.
public const string FormatDecimal = "format.decimal"
Field Value
FormatDuration
Not a valid duration or time span.
public const string FormatDuration = "format.duration"
Field Value
FormatGuid
Not a valid GUID.
public const string FormatGuid = "format.guid"
Field Value
FormatInteger
Not a valid integer. Covers byte, short, int and long, including out-of-range-for-type.
public const string FormatInteger = "format.integer"
Field Value
FormatNumber
Not a valid floating-point number (double, float).
public const string FormatNumber = "format.number"
Field Value
FormatTime
Not a valid time of day.
public const string FormatTime = "format.time"
Field Value
HttpBadRequest
An upstream HTTP response was 400.
public const string HttpBadRequest = "http.bad-request"
Field Value
HttpConflict
An upstream HTTP response was 409.
public const string HttpConflict = "http.conflict"
Field Value
HttpForbidden
An upstream HTTP response was 403.
public const string HttpForbidden = "http.forbidden"
Field Value
HttpUnprocessableContent
An upstream HTTP response was 422.
public const string HttpUnprocessableContent = "http.unprocessable-content"
Field Value
LegacyUnspecified
The placeholder that predates this vocabulary. Producers no longer emit it; every projection maps it onto Unspecified so an application that adopted it keeps working.
public const string LegacyUnspecified = "validation.error"
Field Value
MoneyCurrencyMismatch
An operation combined two amounts in different currencies. Carries expected and actual.
public const string MoneyCurrencyMismatch = "money.currency-mismatch"
Field Value
MoneyNegativeResult
An operation would produce a negative amount where none is permitted.
public const string MoneyNegativeResult = "money.negative-result"
Field Value
NumberFinite
A floating-point number is NaN or infinity where a finite value is required.
public const string NumberFinite = "number.finite"
Field Value
NumberOverflow
An arithmetic operation overflowed. Never a parse failure — that is format.*.
public const string NumberOverflow = "number.overflow"
Field Value
NumberPrecision
Scale or precision exceeds what the target permits.
public const string NumberPrecision = "number.precision"
Field Value
PageSizeOutOfRange
A page size was not positive, or exceeded the permitted maximum.
public const string PageSizeOutOfRange = "page-size.out-of-range"
Field Value
SchedulePeriodsOverlap
Weekly schedule periods overlap, including across the week boundary.
public const string SchedulePeriodsOverlap = "schedule.periods-overlap"
Field Value
StringCountryCode
Not a valid ISO 3166 country code.
public const string StringCountryCode = "string.country-code"
Field Value
StringCreditCard
Not a valid credit card number.
public const string StringCreditCard = "string.credit-card"
Field Value
StringCurrencyCode
Not a valid ISO 4217 currency code.
public const string StringCurrencyCode = "string.currency-code"
Field Value
StringEmail
Not a valid email address.
public const string StringEmail = "string.email"
Field Value
StringExactLength
Not the one permitted length.
public const string StringExactLength = "string.exact-length"
Field Value
StringHostname
Not a valid host name.
public const string StringHostname = "string.hostname"
Field Value
StringIpAddress
Not a valid IP address.
public const string StringIpAddress = "string.ip-address"
Field Value
StringLanguageCode
Not a valid ISO 639 language code.
public const string StringLanguageCode = "string.language-code"
Field Value
StringLength
Length outside the permitted range.
public const string StringLength = "string.length"
Field Value
StringMaxLength
Longer than the permitted maximum.
public const string StringMaxLength = "string.max-length"
Field Value
StringMinLength
Shorter than the permitted minimum.
public const string StringMinLength = "string.min-length"
Field Value
StringPattern
Did not match the required pattern.
public const string StringPattern = "string.pattern"
Field Value
StringPhoneE164
Not a valid E.164 telephone number.
public const string StringPhoneE164 = "string.phone-e164"
Field Value
StringSlug
Not a valid URL slug.
public const string StringSlug = "string.slug"
Field Value
StringTimeZoneIana
Not an IANA time-zone identifier available on the current system.
public const string StringTimeZoneIana = "string.time-zone-iana"
Field Value
StringUrl
Not a valid URL.
public const string StringUrl = "string.url"
Field Value
Unspecified
Emitted when a producer has made no finer code decision. The only string on the wire meaning "no reason available", and it appears at no site meaning anything else.
public const string Unspecified = "error.unspecified"
Field Value
ValueBetweenExclusive
Outside an exclusive range.
public const string ValueBetweenExclusive = "value.between-exclusive"
Field Value
ValueBetweenInclusive
Outside an inclusive range.
public const string ValueBetweenInclusive = "value.between-inclusive"
Field Value
ValueGreaterThan
Not greater than the comparison value.
public const string ValueGreaterThan = "value.greater-than"
Field Value
ValueGreaterThanOrEqual
Not greater than or equal to the comparison value.
public const string ValueGreaterThanOrEqual = "value.greater-than-or-equal"
Field Value
ValueLessThan
Not less than the comparison value.
public const string ValueLessThan = "value.less-than"
Field Value
ValueLessThanOrEqual
Not less than or equal to the comparison value.
public const string ValueLessThanOrEqual = "value.less-than-or-equal"
Field Value
ValueMustBeEmpty
A value was required to be empty and was not.
public const string ValueMustBeEmpty = "value.must-be-empty"
Field Value
ValueMustBeNull
A value was required to be null and was not.
public const string ValueMustBeNull = "value.must-be-null"
Field Value
ValueMustEqual
Did not equal the required value.
public const string ValueMustEqual = "value.must-equal"
Field Value
ValueMustNotEqual
Equalled a forbidden value.
public const string ValueMustNotEqual = "value.must-not-equal"
Field Value
ValueNotDefault
A value was the CLR default when a non-default was required — Guid.Empty,
DateTime.MinValue, numeric zero. Distinct from ValueNotEmpty: zero is not
empty, and only the string case is genuinely emptiness.
public const string ValueNotDefault = "value.not-default"
Field Value
ValueNotEmpty
A value was present but empty.
public const string ValueNotEmpty = "value.not-empty"
Field Value
ValueNotNull
A required value was null.
public const string ValueNotNull = "value.not-null"
Field Value
Methods
FormatCodeFor(Type)
Returns the format.* code for "this input could not be read as type".
public static string FormatCodeFor(Type type)
Parameters
typeTypeThe target CLR type. A nullable value type is unwrapped first.
Returns
- string
The matching
format.*code, or FormatConversion when no more specific code applies.
Remarks
Producer independence is the point: a value that fails to parse must report the same code whether it arrived as a query parameter, as a JSON scalar, or nested inside a composite. The mapping lives here, once, so a new producer cannot quietly invent a different answer for a failure the framework already has a code for.