# ARX error codes (PostgreSQL)

Every error an ARX call throws is an `ArxException` with a stable `Code` (`ArxErrorCode`), the same in every provider (a misuse found while the schema catalog is built at startup, such as a table declared twice, is an `ArgumentException`). The message starts with it (`ARX3001 UniqueViolation: …`) and the thousands digit is its `Category`. Catch by code, on the base class: `catch (ArxException e) when (e.Code == ArxErrorCode.RecordNotFound)`. Some codes come as a subclass (`ArxValidationException` before the database, `ArxDatabaseException` from it, `ArxNotSupportedException` for ARX8001), but not every one: a record not found (ARX2002) can be the base class, so a catch of a subclass can miss it. Retry only when `IsTransient` is true. The database's own error stays on the exception: `SqlState`, and the driver's exception as `InnerException`.

## ARX1xxx Validation

ARX refused the call before sending it: invalid input, a misused connection, transaction or batch scope, or a name that looks like SQL injection.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX1001 | `InvalidArgument` | Invalid input not covered by a more specific code. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1002 | `MissingEntityName` | The entity name is null or blank. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1003 | `InvalidIdentifier` | An entity or attribute name fails the identifier rules. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1004 | `DuplicateAttribute` | The same attribute appears more than once (names are case-insensitive). | no | no database error maps to it (ARX itself can still raise it) |
| ARX1005 | `InvalidLookup` | A lookup (`ArxEntityReference`) has no usable Id. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1006 | `InvalidSelectionSet` | A selection set value has no option set name. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1007 | `UnsupportedValueType` | An attribute value has a type the provider can't write. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1008 | `InvalidConnection` | The connection or transaction is of the wrong driver type, or the service has no connection string. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1009 | `TransactionMismatch` | The transaction belongs to a different connection. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1010 | `TransactionCompleted` | The transaction has already been committed, rolled back or disposed. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1011 | `SelectionSetValueNotAllowed` | A selection set value isn't allowed by its set in the catalog: not one of its options, of the wrong kind, a retired option, several values for a single-choice set, a duplicate, or a value the set's storage can't hold. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1012 | `UnknownSelectionSet` | A selection set value names a set that isn't in the catalog, or no catalog was supplied. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1013 | `InvalidDateTimeValue` | A date or time value that would be stored as something else than the caller meant: default(DateTime), default(DateTimeOffset) or default(DateOnly) (no real date: a database would store a sentinel or refuse it), or an array mixing UTC and Unspecified DateTime values. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1014 | `BatchScopeBusy` | A batch scope was called while another call on it was still running. A scope holds one connection, which runs one command at a time: await each call before the next. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1015 | `TransactionAborted` | A call or a commit on a transaction that an earlier failed call has aborted. The database has already discarded the transaction's work; it can only be rolled back. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1016 | `IdNotDeclared` | The entity's table isn't declared in the service's schema catalog, and the entity doesn't declare its own id column. A service with a catalog uses only what is declared: ARX doesn't guess an id column. A service created without a catalog reads the table's primary key instead (where the provider can), and raises `TableNotResolvable` when it can't. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1017 | `SuspectedInjection` | A name (entity, attribute, match column or type) contains SQL syntax: a quote, a statement separator, a comment marker, a bracket, an operator or an SQL keyword after a space. That is the shape of an SQL injection attempt, not of a typo, so it gets its own code to alert on. Refused before the database: nothing was sent. Values are never checked for this: they are always parameters, and any text is stored as typed. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1018 | `NotPreloaded` | The service is `Strict` and the call names a table or column that wasn't preloaded: refused before the database. Preload it, or turn Strict off. | no | no database error maps to it (ARX itself can still raise it) |
| ARX1019 | `TableNotResolvable` | A service without a schema catalog resolves each table from the database, and this table has no id the call can use: no primary key, a primary key of several columns, or one of a type ARX can't use as an id. Refused before anything is sent, only for a call that needs the id (Create, Retrieve, Update or Delete by id). Declare the table in a schema catalog (`ArxIdColumn.NoIdColumn`), or match by a key or columns. | no | no database error maps to it (ARX itself can still raise it) |

## ARX2xxx NotFound

The rows the call addressed weren't found as asked: none, several where one was required, or one at another version than the call carried (ARX2004). Nothing was changed.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX2002 | `RecordNotFound` | The record addressed by key doesn't exist. | no | no database error maps to it (ARX itself can still raise it) |
| ARX2003 | `MultipleRecordsMatched` | An update or delete with `RequireSingleRow` found more than one row for an entity. Nothing was changed. | no | no database error maps to it (ARX itself can still raise it) |
| ARX2004 | `RecordChanged` | The record was changed since it was read: an Update or Delete carried a version (optimistic concurrency) that isn't the record's any more. Nothing was changed: read it again, and apply the change to what is there now. | no | no database error maps to it (ARX itself can still raise it) |

## ARX3xxx Constraint

The database refused the change because of a rule: a unique key, a foreign key, NOT NULL, CHECK, or a routine's own error.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX3001 | `UniqueViolation` | A unique constraint or key was violated. | no | `23505` unique_violation |
| ARX3002 | `ForeignKeyViolation` | A referenced record is missing, or a record is still referenced. | no | `23503` foreign_key_violation |
| ARX3003 | `NotNullViolation` | A required attribute has no value. | no | `23502` not_null_violation |
| ARX3004 | `CheckViolation` | A check constraint or validation rule failed. | no | `23514` check_violation |
| ARX3005 | `RaisedByDatabase` | A routine the database runs (a procedure or function) refused the call on purpose (PostgreSQL `RAISE EXCEPTION`, SQL Server `THROW`, MySQL `SIGNAL`). On PostgreSQL: `RAISE EXCEPTION` (SQLSTATE P0001), an `ASSERT` or a state of the routine's own (`USING ERRCODE = 'AX001'`). The message is the routine's; `SqlState`, `Detail` and `Hint` are its own. | no | `P0001` raise_exception; `P0004` assert_failure; a routine's own SQLSTATE |

## ARX4xxx Data

A value doesn't fit its column: out of range, too long, in the wrong format or of the wrong type.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX4001 | `ValueOutOfRange` | A number is outside the column's range. | no | `22003` numeric_value_out_of_range |
| ARX4002 | `ValueTooLong` | Text or binary data is longer than the column allows. | no | `22001` string_data_right_truncation |
| ARX4003 | `InvalidValueFormat` | A value can't be parsed for its column (for example invalid JSON, dates or encoding). | no | `22007` invalid_datetime_format; `22008` datetime_field_overflow; `22021` character_not_in_repertoire; `22P02` invalid_text_representation; `22P05` untranslatable_character |
| ARX4004 | `DataTypeMismatch` | A value's type doesn't fit the column. | no | `42725` ambiguous_function; `42804` datatype_mismatch; `42883` undefined_function |

## ARX5xxx Schema

A table or column doesn't exist, or a declaration in the schema catalog doesn't match the table.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX5001 | `UndefinedEntity` | The table or collection doesn't exist. | no | `42P01` undefined_table |
| ARX5002 | `UndefinedAttribute` | The column doesn't exist or can't be written. | no | `42703` undefined_column; `42803` grouping_error; `428C9` generated_always |
| ARX5003 | `SchemaMismatch` | A declaration in the schema catalog doesn't match the table: the database returned an id of another type, or `ValidateSchemaAsync` found a difference. The exception says whether rows were stored. | no | no database error maps to it (ARX itself can still raise it) |

## ARX6xxx Permission

The database user isn't allowed to do it.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX6001 | `PermissionDenied` | The database user lacks the required permission. | no | `25006` read_only_sql_transaction; `42501` insufficient_privilege; `28xxx` any of class 28 |

## ARX7xxx Transient

A temporary failure: a deadlock, a conflict, a timeout, throttling or a lost connection. Safe to retry the whole operation (`IsTransient` is true).

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX7001 | `Deadlock` | The operation was chosen as a deadlock victim. Safe to retry. | yes | `40P01` deadlock_detected |
| ARX7002 | `SerializationFailure` | The operation conflicted with a concurrent transaction. Safe to retry. | yes | `40001` serialization_failure |
| ARX7003 | `Timeout` | The command or a lock wait timed out. Safe to retry. | yes | `55P03` lock_not_available; `57014` query_canceled |
| ARX7004 | `Throttled` | The server is rate-limiting or out of connections. Safe to retry later. | yes | `53300` too_many_connections |
| ARX7005 | `ConnectionFailure` | The database couldn't be reached, or the connection dropped. Safe to retry. | yes | `3D000` invalid_catalog_name; `57P01` admin_shutdown; `57P02` crash_shutdown; `57P03` cannot_connect_now; `08xxx` any of class 08 |

## ARX8xxx NotSupported

The provider can't do what was asked, and refuses it rather than ignoring part of it.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX8001 | `NotSupported` | The provider doesn't support the requested operation or feature. | no | `0A000` feature_not_supported; `2D000` invalid_transaction_termination; `34000` invalid_cursor_name; `42601` syntax_error; `42809` wrong_object_type; `55000` object_not_in_prerequisite_state |

## ARX9xxx Provider

A database error ARX doesn't map; the exception keeps its native code and SQLSTATE.

| Code | Name | Meaning | Safe to retry | From PostgreSQL |
|---|---|---|---|---|
| ARX9001 | `ProviderError` | A native error the provider doesn't map; see NativeCode and SqlState. | no | any other SQLSTATE |

