# 08003 — connection_does_not_exist

> PostgreSQL SQLSTATE 08003: connection_does_not_exist, source-backed diagnosis and recovery guidance.
---

# 08003

## At a glance {#at-a-glance}

SQLSTATE `08003` is **connection_does_not_exist** in Class `08`. `08003` identifies a missing named connection handle in the current dblink backend session. It is a handle-lifecycle error, not evidence that the remote server is down (08001) or that an established socket failed (08006). The selected path first disconnects `missing_remote`, then proves a real handle can be opened, queried, and disconnected.

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| Field | Value |
| --- | --- |
| SQLSTATE | `08003` |
| Condition | `connection_does_not_exist` |
| Status | `active` |
| Known present by | `7.4` |
| Locked snapshots | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_CONNECTION_DOES_NOT_EXIST` |
| Aliases | `—` |

<!-- source facts: data/errcodes/08003.json -->
<!-- END SQLSTATE FACTS -->

## Meaning {#meaning}

This condition comes from the dblink handle lookup, before any remote SQL is run: the current backend has no named connection matching the request. The primary is assembled as `connection "%s" not available`, so the name identifies the local handle lifecycle, not remote reachability. A missing handle is therefore distinct from 08001 establishment failure and 08006 loss of an established connection.

The lookup is local to one PostgreSQL backend. A pool may give two clients the same application-level connection name while their dblink handle maps are different; creating `working_remote` on one backend does not repair `missing_remote` on another. The fixed branch has no DETAIL or HINT, so the quoted handle name and the session that issued the call are the first facts to preserve.

## Diagnosis {#diagnosis}

Check the exact dblink name and the session or pool connection that owns it. The primary is dynamically assembled as `connection "missing_remote" not available`; in the selected autocommit run the failed lookup stays `IDLE`, and the repaired handle returns remote `1` before `dblink_disconnect` returns `OK`.

Separate a lookup failure from a lost socket. If the name was never opened on this backend, inspect the handle-creation path and pool checkout; if it was opened and a later remote call fails, collect that call's diagnostics before deciding whether to disconnect and recreate it. In an explicit local transaction, this dblink `ERROR` follows the normal transaction-abort boundary and requires rollback or a deliberately established savepoint before unrelated statements. The selected `IDLE` result is specifically the autocommit case.

## Response {#response}

Create the named handle on the same session that will use it, or make an absent-handle disconnect explicitly idempotent. After a real remote operation, reconcile its result before closing or recreating a handle; do not reconnect every pool member merely because one session forgot a dblink name.

For autocommit, opening, probing, and disconnecting on the same backend is a complete lifecycle. For an explicit transaction, recover the local transaction first, then recreate the handle on that same backend; a successful new handle does not tell you whether an earlier remote operation committed. Keep handle names and ownership visible in pool diagnostics so a reconnect does not silently move work to another session.

## Observed diagnostics {#messages}

The fixed handle-lookup branch emits `ERROR` with primary `connection "%s" not available`; the requested handle name is dynamic and there is no fixed DETAIL or HINT. A client exception without this server diagnostic does not establish 08003.

The selected primary `connection "missing_remote" not available` is therefore a concrete name lookup, not a server reachability test. The fixed `ERROR` severity can leave an explicit transaction in `INERROR`; it left the selected autocommit owner `IDLE` because no surrounding transaction was open.

## Representative case {#case}

<!-- BEGIN SQLSTATE SNIPPET: dblink_missing_connection -->

The SQL block asks `dblink` to disconnect a handle that was never opened, then probes the same session.

The `runner_host`, `runner_port`, `runner_db`, and `runner_user` values are runner placeholders. Replace them with a target and login role for which the owner has dblink and remote-connection privileges. The handle is session-local: run the missing lookup, open/probe, and disconnect on the same backend; the selected case uses autocommit.

```sql
CREATE EXTENSION IF NOT EXISTS dblink;
SELECT dblink_disconnect('missing_remote');
SELECT dblink_connect('working_remote', 'host=runner_host port=runner_port dbname=runner_db user=runner_user connect_timeout=5');
SELECT * FROM dblink('working_remote', 'SELECT 1') AS result(value integer);
SELECT dblink_disconnect('working_remote');
SELECT 1;
```

<!-- END SQLSTATE SNIPPET -->

The selected 18.6 run reports SQLSTATE `08003`, primary `connection "missing_remote" not available`, and leaves the owner session `IDLE` after the failed operation. The controlled repair opened the named handle with `OK`, returned remote `1`, and disconnected it with `OK`; the final owner probe returned `1` and `IDLE`. The 10.21 selected run passed the same assertions.

The downloadable case and evidence projections are [`08003 case JSON`](../data/cases/08003.json) and [`authored evidence`](../data/evidence/08003.json). The runner manifest is `verify/cases/08003/cases.json`; the page SQL is checked against its shared registry before publication.

## Versions {#versions}

The generated facts table records the locked catalogue snapshots and earliest observed definition. The selected natural runtime scope is PostgreSQL 18.6 and 10.21; this does not infer behavior for every intermediate release.

## Related {#related}

- [`08001` — sqlclient_unable_to_establish_sqlconnection](../08001/)
- [`08006` — connection_failure](../08006/)

## Sources {#sources}

- `src.dblink-not-available.18.6` — `contrib/dblink/dblink.c` at `REL_18_6` commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`; fixed blob SHA-256 `e4cfaec3a0a1e5d23fded584725e0f6cf7a17321ad99e5fe046e8b7f97416f15` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/contrib/dblink/dblink.c#L193-L195)).
- `src.dblink-not-available.10.23` — `contrib/dblink/dblink.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `2d542cc722ba361bd59990aaed7fe7c0f8e147155df5e5fcd56ee03b4dd27c61` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/contrib/dblink/dblink.c#L171-L173)).
- `src.calls.REL_18_6` / `src.calls.REL_10_23` — fixed local call scans, SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf` / `00d16d3eb01b71ccf1b245c8f3102f9d0ec9f36fb02777b8dd1b99fcb263040c`; these scans preserve the resolved call context used by the claims.
