Errors
Errors fall into three groups:
- Database errors from Postgres, translated into a typed
PostgresExceptionhierarchy by everyDbContext. - Builder and runtime errors thrown by gisila_orm itself before or after a statement runs.
- Build-time errors from the schema parser and migration generator.
import 'package:gisila_orm/gisila.dart';
try { await authors().insert({'name': 'Ada', 'email': email}).one(db.context());} on PostgresUniqueViolationException catch (e) { print('taken: ${e.details?['constraint']}');} on PostgresException catch (e) { print('database error ${e.sqlState}: ${e.message}');}PostgresException
Section titled “PostgresException”abstract class PostgresException implements Exception { final String message; final String? sqlState; final int? errorCode; final String? query; final Map<String, dynamic>? details;}Base class of every translated server error.
| Field | Description |
|---|---|
message |
The server’s error message. |
sqlState |
Five-character SQLSTATE code, such as 23505. |
errorCode |
Always null for errors mapped from the driver. |
query |
The SQL text that failed, without parameter values. null for errors raised while committing a transaction. |
details |
Map with whichever of these the server sent: detail, hint, table, column, constraint, schema. |
When to use: catch specific subclasses for errors you can handle (a unique
violation means “already exists”), and PostgresException as a fallback.
Errors raised by the driver itself (connection refused, timeouts, closed pool)
are not ServerExceptions and pass through untranslated.
SQLSTATE mapping
Section titled “SQLSTATE mapping”PostgresErrorMapper produces these classes. Any other SQLSTATE becomes
PostgresUnknownException.
| SQLSTATE | Class | Parent |
|---|---|---|
00000 |
PostgresSuccessException |
PostgresException |
01xxx (listed codes) |
PostgresWarningException |
PostgresException |
02000, 02001 |
PostgresNoDataException |
PostgresException |
08000, 08001, 08003, 08004, 08006, 08007 |
PostgresConnectionException |
PostgresException |
08P01 |
PostgresProtocolViolationException |
PostgresConnectionException |
0A000 |
PostgresFeatureNotSupportedException |
PostgresException |
21000 |
PostgresCardinalityViolationException |
PostgresException |
22000, 22021, 22024, 22025, 2202E, 2202F, 2202H |
PostgresDataException |
PostgresException |
22001 |
PostgresStringDataTruncationException |
PostgresDataException |
22003 |
PostgresNumericValueOutOfRangeException |
PostgresDataException |
22007, 22008 |
PostgresInvalidDatetimeException |
PostgresDataException |
22012 |
PostgresDivisionByZeroException |
PostgresDataException |
23000, 23001 |
PostgresIntegrityConstraintViolationException |
PostgresException |
23502 |
PostgresNotNullViolationException |
PostgresIntegrityConstraintViolationException |
23503 |
PostgresForeignKeyViolationException |
PostgresIntegrityConstraintViolationException |
23505 |
PostgresUniqueViolationException |
PostgresIntegrityConstraintViolationException |
23514 |
PostgresCheckViolationException |
PostgresIntegrityConstraintViolationException |
23P01 |
PostgresExclusionViolationException |
PostgresIntegrityConstraintViolationException |
24000 |
PostgresInvalidCursorStateException |
PostgresCursorException |
25000-25008, 25P01, 25P02 |
PostgresInvalidTransactionStateException |
PostgresTransactionException |
| anything else | PostgresUnknownException |
PostgresException |
25P02 (“current transaction is aborted”) is what you get when you keep using
a transaction after one of its statements failed.
Classes the mapper doesn’t produce
Section titled “Classes the mapper doesn’t produce”These are exported and part of the hierarchy, but no SQLSTATE maps to them in
0.2.1. Errors such as serialization failures (40001), deadlocks (40P01),
undefined tables (42P01) and syntax errors (42601) arrive as
PostgresUnknownException; check sqlState.
PostgresSyntaxException, PostgresUndefinedTableException,
PostgresUndefinedColumnException, PostgresInsufficientPrivilegeException,
PostgresTransactionException, PostgresSerializationFailureException,
PostgresDeadlockDetectedException, PostgresLockTimeoutException,
PostgresSystemException, PostgresInsufficientResourcesException,
PostgresDiskFullException, PostgresTooManyConnectionsException,
PostgresProgramLimitExceededException, PostgresConfigFileException,
PostgresAuthenticationException, PostgresInvalidAuthorizationException,
PostgresInvalidPasswordException, PostgresCursorException,
PostgresInternalException, PostgresSavepointException,
PostgresPlPgSqlException, PostgresExternalRoutineException,
PostgresOperatorInterventionException, PostgresQueryCancelledException.
Example: retry a serializable transaction.
Future<R> withRetry<R>(Future<R> Function() run, {int attempts = 3}) async { for (var i = 1;; i++) { try { return await run(); } on PostgresException catch (e) { final retryable = e.sqlState == '40001' || e.sqlState == '40P01'; if (!retryable || i == attempts) rethrow; } }}PostgresErrorMapper
Section titled “PostgresErrorMapper”class PostgresErrorMapper { static PostgresException mapError(String message, String? sqlState, int? errorCode, String? query, Map<String, dynamic>? details); static PostgresException fromServerException(ServerException e, {String? query});}The translation table above. Every DbContext calls fromServerException for
you. Call it yourself only if you run statements through package:postgres
directly and want the same exception types.
Query builder exceptions
Section titled “Query builder exceptions”| Exception | Thrown by | When |
|---|---|---|
QueryNoRowsException |
Query.one |
No row matched. |
QueryMultipleRowsException |
Query.one |
More than one row matched. |
InsertReturnedNoRowsException |
InsertQuery.one |
Nothing came back (returning(false), or ON CONFLICT DO NOTHING skipped the row). |
InvalidQueryBuilderException |
compile / run on mutations |
An insert with no rows, an update with no values, or an update or delete with no WHERE and no .all(). |
PreloadException |
Preloader |
A parent model doesn’t mix in Preloadable (regenerate your models). |
ArgumentError |
InsertQuery.compile, onConflictDoUpdate, RawSql compile |
Rows with different columns; empty conflict target; placeholder/parameter mismatch. |
StateError |
any query on a closed Database |
Database.close() was called. |
Each has a message field.
Author? author;try { author = await authors().where(AuthorTable.email.eq(email)).one(ctx);} on QueryNoRowsException { author = null; // or use first(ctx), which returns null instead of throwing}DatabaseConfigurationException
Section titled “DatabaseConfigurationException”Thrown when a named connection can’t be resolved (Database.connect,
DatabaseConfig.defaultConnection, db.context('missing')) or an
ssl_root_cert file can’t be loaded. Has a message field.
Migration exceptions
Section titled “Migration exceptions”| Exception | Thrown by | When |
|---|---|---|
MigrationChecksumException |
MigrationManager.up |
Applied migrations were edited. ids lists them. |
MigrationRollbackException |
MigrationManager.down |
A migration to roll back has no file in the discovered set, or an empty down SQL. |
DestructiveMigrationException |
SchemaDiffer.generateMigrationFile, generate, migrate diff |
The diff would lose data and wasn’t allowed. changes lists it. |
SchemaValidationException
Section titled “SchemaValidationException”class SchemaValidationException implements Exception { final List<SchemaError> errors; bool get hasErrors; String format({bool? color});}
class SchemaError { final String code; final String message; final SourceSpan span; final SchemaErrorLevel level; // error | warning final String? hint; final List<String> notes;}Thrown by SchemaDefinition.fromYaml, fromFile and fromProject with every
problem found. format() renders them with file, line, column, a caret under
the offending token and the hint; color defaults to auto-detection
(respecting NO_COLOR). Exported from
package:gisila_orm/generators/schema_parser.dart. The error codes are listed
in Schema YAML format.
Other exported exceptions
Section titled “Other exported exceptions”| Exception | Description |
|---|---|
DefaultValueException |
An invalid default: value when generating SQL. Field msg. |
QueryException |
Legacy; not thrown by current code. Field msg. |
ValidationException |
Legacy; not thrown by current code. Field errors. |
HTTP mapping in gisila apps
Section titled “HTTP mapping in gisila apps”package:gisila_orm/web.dart provides PostgresDbErrorMapper, which turns
these exceptions into HTTP errors. See
gisila integration.
See also: Database, contexts and transactions, Migrations API.