hasql
Safe HaskellNone
LanguageHaskell2010

Hasql.Errors

Description

Explicit error types for all Hasql operations.

This module provides access to all error types used throughout Hasql:

  • AcquireError - errors that occur when establishing a database connection
  • UseError - errors returned when using a connection
  • SessionError - recoverable errors that occur during session execution

The module follows Hasql's philosophy of explicit error handling, where all errors are represented as values rather than exceptions.

Synopsis

Error class

class IsError a where #

A class for types that can be treated as errors.

This is a rendering interface: it turns an error value into a human-readable message, a list of dynamic details, and - where the error carries one - the server's SQLSTATE. It deliberately does not offer a retryability verdict. Whether an operation is worth retrying depends on the caller's retry policy, the transaction it sits inside, and the SQLSTATE where one is available - not on a boolean this class hands out. Hasql declines to own that decision, so the omission here is not an oversight.

Minimal complete definition

toMessage, toDetails

Methods

toMessage :: a -> Text #

Convert the error to a human-readable message with no dynamic details.

toDetails :: a -> [(Text, Text)] #

Convert the error to a list of key-value pairs of dynamic details.

toSqlState :: a -> Maybe Text #

The SQLSTATE the server reported, if this error carries one at all.

Lets you branch on a PostgreSQL error code without knowing which constructors of which error type the server error is nested under. For the code vocabulary see https://www.postgresql.org/docs/current/errcodes-appendix.html.

Nothing means the error carries no server code: a connection failure, a decoding failure, a driver bug. It never means "the operation succeeded".

The default implementation returns Nothing, which is correct only for error types that can never carry a server error. A type that wraps another error type MUST override it and delegate to the wrapped value, otherwise it silently reports Nothing for codes it does in fact carry.

Instances

Instances details
IsError AcquireError # 
Instance details

Defined in Hasql.Errors

IsError CellError # 
Instance details

Defined in Hasql.Errors

IsError RowError # 
Instance details

Defined in Hasql.Errors

IsError ServerError # 
Instance details

Defined in Hasql.Errors

IsError SessionError # 
Instance details

Defined in Hasql.Errors

IsError StatementError # 
Instance details

Defined in Hasql.Errors

IsError UseError # 
Instance details

Defined in Hasql.Errors

toDetailedText :: IsError e => e -> Text #

Convert the error to a multiline detailed human-readable text representation containing all details.

Acquire errors

data AcquireError #

Error that occurs when attempting to establish a database connection.

These errors can occur when calling acquire, which runs three stages in sequence: it establishes a connection, checks the server version, and initializes session settings. A constructor is named for its stage, then its case: a bare stage name means nothing further is known at that stage, and a stage with only one case needs no prefix. Reaching a stage is therefore a claim about everything before it - a failure at initialization means the connection was established and the server version was accepted.

Every constructor here publishes only what the driver actually observed. libpq produces no structured signal for a failure while connecting - no ServerError is available - so ConnectionAcquireError and ConnectionPasswordRequiredAcquireError carry prose. A failure during session initialization can go either way, hence the split between InitializationConnectionLossAcquireError and InitializationServerErrorAcquireError.

Constructors

ConnectionAcquireError

The connection could not be established, and no structured signal exists to say why.

This is the residual case at the connection stage: DNS failure, connection refused, TLS negotiation failure, a rejected password, a missing database, and any other rejection libpq does not surface a flag for, all land here alike.

Fields

  • Text

    Human readable details from libpq, intended for logging. May be empty.

ConnectionPasswordRequiredAcquireError

The server demanded a password and none was available.

Reported from PQconnectionNeedsPassword, a flag libpq sets from the authentication exchange rather than from message text. A wrong password, by contrast, reports False on this flag and is indistinguishable from any other connection refusal, so it lands in ConnectionAcquireError instead.

Fields

  • Text

    Human readable details from libpq, intended for logging.

VersionTooOldAcquireError

The server's version is below the minimum this driver supports.

The three fields are the server's major, minor and patch version, in that order. The minimum required version is not carried alongside them: it is a constant of this library, currently 9.0.0.

Fields

  • Int

    Major version.

  • Int

    Minor version.

  • Int

    Patch version.

InitializationConnectionLossAcquireError

Session initialization failed and the connection died: there is prose and nothing else.

This covers both PQexec returning no result at all and PQexec returning a result libpq fabricated client-side with no diagnostic fields on it - the same event either way, distinguished from InitializationServerErrorAcquireError by whether the result carries a SQLSTATE, not by whether a result exists.

Fields

  • Text

    Human readable details from libpq, intended for logging. May be empty.

InitializationServerErrorAcquireError ServerError

Session initialization failed and the server said why.

The server rejected the initialization statement and returned a real error report, readable through PQresultErrorField. This is the one AcquireError for which toSqlState can return Just.

Instances

Instances details
Eq AcquireError # 
Instance details

Defined in Hasql.Engine.Errors

Show AcquireError # 
Instance details

Defined in Hasql.Engine.Errors

IsError AcquireError # 
Instance details

Defined in Hasql.Errors

Use errors

data UseError #

Error that use can return.

SessionUseError means the connection is still usable and is the only constructor catchError on a Session can see. ConnectionUseError means the connection is gone, and no handler inside the session can intercept it - the split is structural, enforced by the Session Monad instance rather than by any check a handler has to remember to make.

Constructors

SessionUseError SessionError

The session reported an ordinary failure and the connection is still usable.

ConnectionUseError

The connection is gone.

This covers every way use can lose the connection: a dropped socket, a request libpq refused to send outright (e.g. more than 65535 parameters in one statement), an unexpected response from the server, or a bug in Hasql. The reason text says which.

use has finished the connection before returning this, so the Connection the session ran on is spent: further use on it fails with this same error, and release is a no-op. Pools must discard it rather than return it.

Whatever the cause, the driver cannot vouch for the protocol state of a connection a request failed to leave, and repairing one costs more than replacing it: the repair would have to push a Sync, which flushes and commits the very commands the failed session never got to complete. So this is reported uniformly rather than split by cause - retry policy belongs to the caller, informed by the reason text and, for server errors, toSqlState.

Fields

  • Text

    Human-readable details about what went wrong.

Instances

Instances details
Eq UseError # 
Instance details

Defined in Hasql.Engine.Errors

Show UseError # 
Instance details

Defined in Hasql.Engine.Errors

IsError UseError # 
Instance details

Defined in Hasql.Errors

Session errors

data SessionError #

Error that occurs during session execution and leaves the connection usable.

A session is a batch of actions executed in a database connection context. Every constructor here means the connection is still fit to be handed back for reuse - that is the axis SessionError is narrowed on, not provenance. A failure that leaves the connection gone is not a SessionError at all; it is one of the other two constructors of UseError.

Session errors provide detailed context to help diagnose problems, including SQL text, parameters, and the location of the error within a pipeline of statements.

Constructors

StatementSessionError

An error occurred while executing a statement in the session.

This wraps statement-level errors and provides additional context about:

  • Which statement in the pipeline failed (when multiple statements are batched)
  • The SQL text and parameters of the failing statement
  • Whether the statement was prepared or unprepared

The error message includes formatted output showing all this context, making it easier to diagnose issues in production.

Fields

  • Int

    Total number of statements in the running pipeline. 1 if it's executed alone.

  • Int

    0-based index of the statement that failed. 0 if it's executed alone.

  • Text

    SQL template of the failing statement.

  • [Text]

    Parameter values as text (for logging purposes).

  • Bool

    Whether the statement was executed as a prepared one.

  • StatementError

    The underlying statement error.

ScriptSessionError

An error occurred while executing a script.

Scripts are multi-statement SQL texts executed via script. Unlike regular statements, scripts don't support parameters or result decoding, and errors are limited to server-reported issues.

Fields

MissingTypesSessionError

One or more types referenced in the statement could not be found in the database.

This occurs when using custom types (enums, composite types, domains) that are resolved by name at runtime, but the types don't exist in the database.

To fix this error:

  • Ensure the types are defined in the database
  • Check that schema search paths are configured correctly
  • Verify that the type names in your code match those in the database

Fields

  • (HashSet (Maybe Text, Text))

    Set of (schema name, type name) pairs that could not be found.

    Schema name is Nothing when the type was looked up without a schema qualifier.

Instances

Instances details
Eq SessionError # 
Instance details

Defined in Hasql.Engine.Errors

Show SessionError # 
Instance details

Defined in Hasql.Engine.Errors

IsError SessionError # 
Instance details

Defined in Hasql.Errors

MonadError SessionError Session #

Ranges over SessionError only. throwError can only construct SessionUseError, and catchError only ever sees that constructor - ConnectionUseError flows past both untouched. See the note on the Session type.

Instance details

Defined in Hasql.Engine.Contexts.Session

data StatementError #

Error that occurs when executing a single statement.

Statement errors can be caused by server-side issues (SQL errors, constraint violations) or by mismatches between the decoder specification and the actual result structure (wrong number of rows/columns, type mismatches, or cell-level decoding failures).

Constructors

ServerStatementError ServerError

The server rejected the statement and returned an error.

This includes SQL syntax errors, constraint violations, permission errors, and any other error reported by PostgreSQL during statement execution.

UnexpectedRowCountStatementError

The statement returned a different number of rows than expected.

This occurs when using result decoders like Decoders.singleRow or Decoders.rowsAffectedAtLeast that have specific row count expectations.

Fields

  • Int

    Expected minimum number of rows.

  • Int

    Expected maximum number of rows.

  • Int

    Actual number of rows returned.

UnexpectedColumnCountStatementError

The statement returned a different number of columns than expected.

This indicates a mismatch between the decoder specification and the actual result structure, possibly due to:

  • Schema changes (columns added or removed)
  • Wrong query (selecting different columns than expected)
  • Decoder configuration error

Fields

  • Int

    Expected number of columns.

  • Int

    Actual number of columns returned.

UnexpectedColumnTypeStatementError

A column has a different type than expected.

This occurs when the decoder expects a specific PostgreSQL type (by OID) but the actual column has a different type. This can happen due to:

  • Schema changes (column type changed)
  • Wrong query (selecting wrong column or using a cast)
  • Decoder configuration error

Note: As of version 1.10, Hasql performs strict type checking and will report this error instead of attempting automatic type coercion.

Fields

  • Int

    0-based column index where the type mismatch occurred.

  • Word32

    Expected PostgreSQL type OID.

  • Word32

    Actual PostgreSQL type OID of the column.

RowStatementError

An error occurred while decoding a specific row.

This wraps errors that occur at the row or cell level, providing context about which row failed.

Fields

  • Int

    0-based index of the row that failed to decode.

  • RowError

    The underlying row-level error.

UnexpectedResultStatementError

The database returned an unexpected result structure.

This is a catch-all error that indicates either:

  • An improper statement (e.g., executing a query that doesn't match expectations)
  • A schema mismatch between the code and database
  • A bug in Hasql or server misbehavior

Fields

  • Text

    Human-readable details about what went wrong.

data RowError #

Error that occurs when decoding a result row.

Row errors indicate problems when processing an individual row from the result set, either at the cell level or during row refinement/validation.

Constructors

CellRowError

An error occurred while decoding a specific cell in the row.

This wraps cell-level errors (null handling, deserialization failures) and provides context about which column failed and its type.

Fields

  • Int

    0-based index of the column where the error occurred.

  • Word32

    PostgreSQL type OID of the column, as reported by the server.

  • CellError

    The underlying cell-level error.

RefinementRowError

A refinement or validation error when processing the row.

This occurs when using refinement functions in row decoders (e.g., with refineRow) to validate or transform decoded values. The refinement function rejected the row data.

Fields

  • Text

    Human-readable details about why the refinement failed.

Instances

Instances details
Eq RowError # 
Instance details

Defined in Hasql.Engine.Errors

Show RowError # 
Instance details

Defined in Hasql.Engine.Errors

IsError RowError # 
Instance details

Defined in Hasql.Errors

data CellError #

Error that occurs when decoding a single cell (column value) in a result row.

Cell errors indicate problems with individual values returned by the database, such as unexpected nulls or failures in binary deserialization.

Constructors

UnexpectedNullCellError

A NULL value was encountered when a non-NULL value was expected.

This occurs when using non-nullable decoders (e.g., Decoders.nonNullable) on a column that contains a NULL value.

DeserializationCellError

Failed to deserialize the cell value from its binary representation.

This can occur when:

  • The binary data is corrupted
  • The decoder doesn't match the actual data type
  • The data format is invalid for the expected type

Fields

  • Text

    Human-readable error message describing what went wrong.

Instances

Instances details
Eq CellError # 
Instance details

Defined in Hasql.Engine.Errors

Show CellError # 
Instance details

Defined in Hasql.Engine.Errors

IsError CellError # 
Instance details

Defined in Hasql.Errors

data ServerError #

Error reported by the PostgreSQL server when executing a statement.

The server provides structured error information including error codes (SQL state), messages, and optional context like hints and position information.

For a complete list of PostgreSQL error codes, see: https://www.postgresql.org/docs/current/errcodes-appendix.html

Constructors

ServerError 

Fields

  • Text

    SQL State Code (SQLSTATE).

    A five-character code that identifies the error class and condition. Examples: "23505" (unique violation), "42P01" (undefined table).

  • Text

    Primary error message.

    A human-readable description of the error.

  • (Maybe Text)

    Optional detailed error information.

    Additional context about the error, if available.

  • (Maybe Text)

    Optional hint for resolving the error.

    A suggestion for how to fix the problem, if available.

  • (Maybe Int)

    Optional position in the SQL string where the error occurred.

    A 1-based character index into the SQL string, if the error relates to a specific location in the query.

Instances

Instances details
Eq ServerError # 
Instance details

Defined in Hasql.Engine.Errors

Show ServerError # 
Instance details

Defined in Hasql.Engine.Errors

IsError ServerError # 
Instance details

Defined in Hasql.Errors