Table of Contents

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

string

CursorMalformed

A pagination cursor could not be decoded.

public const string CursorMalformed = "cursor.malformed"

Field Value

string

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

string

EnumUndefined

A value parsed as the enum's underlying type but is not a defined member.

public const string EnumUndefined = "enum.undefined"

Field Value

string

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

string

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

string

FieldsAtLeastOne

None of a group was provided, when at least one is required.

public const string FieldsAtLeastOne = "fields.at-least-one"

Field Value

string

FieldsExactlyOne

None of a group was provided, when exactly one is required.

public const string FieldsExactlyOne = "fields.exactly-one"

Field Value

string

FieldsMutuallyExclusive

More than one of a mutually exclusive group was provided.

public const string FieldsMutuallyExclusive = "fields.mutually-exclusive"

Field Value

string

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

string

FieldsRequiredWith

A field was provided that requires another field which was not.

public const string FieldsRequiredWith = "fields.required-with"

Field Value

string

FormatBoolean

Not a valid boolean.

public const string FormatBoolean = "format.boolean"

Field Value

string

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

string

FormatDate

Not a valid date.

public const string FormatDate = "format.date"

Field Value

string

FormatDateTime

Not a valid date and time.

public const string FormatDateTime = "format.date-time"

Field Value

string

FormatDecimal

Not a valid decimal.

public const string FormatDecimal = "format.decimal"

Field Value

string

FormatDuration

Not a valid duration or time span.

public const string FormatDuration = "format.duration"

Field Value

string

FormatGuid

Not a valid GUID.

public const string FormatGuid = "format.guid"

Field Value

string

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

string

FormatNumber

Not a valid floating-point number (double, float).

public const string FormatNumber = "format.number"

Field Value

string

FormatTime

Not a valid time of day.

public const string FormatTime = "format.time"

Field Value

string

HttpBadRequest

An upstream HTTP response was 400.

public const string HttpBadRequest = "http.bad-request"

Field Value

string

HttpConflict

An upstream HTTP response was 409.

public const string HttpConflict = "http.conflict"

Field Value

string

HttpForbidden

An upstream HTTP response was 403.

public const string HttpForbidden = "http.forbidden"

Field Value

string

HttpUnprocessableContent

An upstream HTTP response was 422.

public const string HttpUnprocessableContent = "http.unprocessable-content"

Field Value

string

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

string

MoneyCurrencyMismatch

An operation combined two amounts in different currencies. Carries expected and actual.

public const string MoneyCurrencyMismatch = "money.currency-mismatch"

Field Value

string

MoneyNegativeResult

An operation would produce a negative amount where none is permitted.

public const string MoneyNegativeResult = "money.negative-result"

Field Value

string

NumberFinite

A floating-point number is NaN or infinity where a finite value is required.

public const string NumberFinite = "number.finite"

Field Value

string

NumberOverflow

An arithmetic operation overflowed. Never a parse failure — that is format.*.

public const string NumberOverflow = "number.overflow"

Field Value

string

NumberPrecision

Scale or precision exceeds what the target permits.

public const string NumberPrecision = "number.precision"

Field Value

string

PageSizeOutOfRange

A page size was not positive, or exceeded the permitted maximum.

public const string PageSizeOutOfRange = "page-size.out-of-range"

Field Value

string

SchedulePeriodsOverlap

Weekly schedule periods overlap, including across the week boundary.

public const string SchedulePeriodsOverlap = "schedule.periods-overlap"

Field Value

string

StringCountryCode

Not a valid ISO 3166 country code.

public const string StringCountryCode = "string.country-code"

Field Value

string

StringCreditCard

Not a valid credit card number.

public const string StringCreditCard = "string.credit-card"

Field Value

string

StringCurrencyCode

Not a valid ISO 4217 currency code.

public const string StringCurrencyCode = "string.currency-code"

Field Value

string

StringEmail

Not a valid email address.

public const string StringEmail = "string.email"

Field Value

string

StringExactLength

Not the one permitted length.

public const string StringExactLength = "string.exact-length"

Field Value

string

StringHostname

Not a valid host name.

public const string StringHostname = "string.hostname"

Field Value

string

StringIpAddress

Not a valid IP address.

public const string StringIpAddress = "string.ip-address"

Field Value

string

StringLanguageCode

Not a valid ISO 639 language code.

public const string StringLanguageCode = "string.language-code"

Field Value

string

StringLength

Length outside the permitted range.

public const string StringLength = "string.length"

Field Value

string

StringMaxLength

Longer than the permitted maximum.

public const string StringMaxLength = "string.max-length"

Field Value

string

StringMinLength

Shorter than the permitted minimum.

public const string StringMinLength = "string.min-length"

Field Value

string

StringPattern

Did not match the required pattern.

public const string StringPattern = "string.pattern"

Field Value

string

StringPhoneE164

Not a valid E.164 telephone number.

public const string StringPhoneE164 = "string.phone-e164"

Field Value

string

StringSlug

Not a valid URL slug.

public const string StringSlug = "string.slug"

Field Value

string

StringTimeZoneIana

Not an IANA time-zone identifier available on the current system.

public const string StringTimeZoneIana = "string.time-zone-iana"

Field Value

string

StringUrl

Not a valid URL.

public const string StringUrl = "string.url"

Field Value

string

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

string

ValueBetweenExclusive

Outside an exclusive range.

public const string ValueBetweenExclusive = "value.between-exclusive"

Field Value

string

ValueBetweenInclusive

Outside an inclusive range.

public const string ValueBetweenInclusive = "value.between-inclusive"

Field Value

string

ValueGreaterThan

Not greater than the comparison value.

public const string ValueGreaterThan = "value.greater-than"

Field Value

string

ValueGreaterThanOrEqual

Not greater than or equal to the comparison value.

public const string ValueGreaterThanOrEqual = "value.greater-than-or-equal"

Field Value

string

ValueLessThan

Not less than the comparison value.

public const string ValueLessThan = "value.less-than"

Field Value

string

ValueLessThanOrEqual

Not less than or equal to the comparison value.

public const string ValueLessThanOrEqual = "value.less-than-or-equal"

Field Value

string

ValueMustBeEmpty

A value was required to be empty and was not.

public const string ValueMustBeEmpty = "value.must-be-empty"

Field Value

string

ValueMustBeNull

A value was required to be null and was not.

public const string ValueMustBeNull = "value.must-be-null"

Field Value

string

ValueMustEqual

Did not equal the required value.

public const string ValueMustEqual = "value.must-equal"

Field Value

string

ValueMustNotEqual

Equalled a forbidden value.

public const string ValueMustNotEqual = "value.must-not-equal"

Field Value

string

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

string

ValueNotEmpty

A value was present but empty.

public const string ValueNotEmpty = "value.not-empty"

Field Value

string

ValueNotNull

A required value was null.

public const string ValueNotNull = "value.not-null"

Field Value

string

Methods

FormatCodeFor(Type)

Returns the format.* code for "this input could not be read as type".

public static string FormatCodeFor(Type type)

Parameters

type Type

The 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.