Decibel.SessionError exception (decibel v1.2.1)

Copy Markdown View Source

Raised when a session handle cannot be used for an operation.

The :reason field is the stable machine-readable failure contract:

  • :not_owner means a structurally valid session handle was used outside the process named by its owner PID, whether the session is live, closed, or its owner has exited. Its exact message is "Session is owned by another process".
  • :closed means the owner tried to use a session it has already closed. Its exact message is "Session is closed".
  • :already_handed_off means an accepted handshake cannot be handed off again. Its exact message is "Session was already handed off".
  • :unknown means the value is not a known owner-local session handle. Legacy bare references from Decibel 0.2, malformed values, and well-shaped owner-local handles that Decibel did not issue use this reason. Its exact message is "Unknown Decibel session".
  • :wrong_phase means the session is live, but the operation is not valid for the current handshake turn or transport phase. Its exact message is "Session operation <operation> requires <expected_phase> phase; current phase is <actual_phase>", with the bracketed values replaced by the corresponding atoms.

Validation first checks the handle shape, then compares its owner PID with the calling process, then performs the owner-local state lookup, and finally validates the phase. Consequently, a structurally valid handle used from another process reports :not_owner before Decibel considers whether owner- local state exists or was closed. This includes a handle retained after its owner exits and a genuine-looking foreign handle.

This owner-PID-only classification is deliberate. Session handles are opaque and must not be constructed or altered by callers. Decibel intentionally has no handle registry, issuance proof, signature, or global verification state, so a constructed or altered owner-local handle may report :closed rather than :unknown.

For :wrong_phase, :operation, :expected_phase, and :actual_phase identify the rejected transition. Those fields are nil for all other reasons.

Summary

Types

The phase or handshake turn of a live session.

The reason a session operation was rejected.

t()

Types

phase()

@type phase() :: :handshake_write | :handshake_read | :handshake | :transport

The phase or handshake turn of a live session.

reason()

@type reason() :: :not_owner | :closed | :already_handed_off | :unknown | :wrong_phase

The reason a session operation was rejected.

t()

@type t() :: %Decibel.SessionError{
  __exception__: true,
  actual_phase: phase() | nil,
  expected_phase: phase() | nil,
  message: String.t(),
  operation: atom() | nil,
  reason: reason()
}