Changes touching this path
- a forge storage error carries the server's own words, so a failed migration stops reporting 'db error' (#776)
pg::storage formatted a postgres::Error with Display, which looks like it
preserves the cause but is the literal string "db error" -- the message,
SQLSTATE, detail and constraint all hang off as_db_error() and were dropped.
connect_failed and migrate.rs's connect error had the same shape.
That is worse than cosmetic. ForgeError::Storage is the ONLY ERROR-level
variant, so the class the forge logs loudest carried nothing actionable; and
--migrate funnels through it, so a failed migration reported 'storage: db
error' with an empty ledger -- indistinguishable from the migration you had
just written being wrong.
Found applying ADR 0043's migration 0004 against a cluster that had defaulted
to WIN1252: the real message named the offending U+26A0 byte sequence and the
encoding, and was visible only in the postgres log on the box. It pointed the
investigation at the new migration instead of at the cluster.
pg::describe now unwraps as_db_error() into message/detail/hint/constraint plus
SQLSTATE, and walks the source chain for non-DbError failures where Display is
equally terse. All three sites route through it.
It deliberately omits the statement and bound parameters: parameters carry
tenant content and this string reaches logs. The server's message plus SQLSTATE
names the fault without naming the data.
before: cannot reach the metadata tier to migrate: db error
after: cannot reach the metadata tier to migrate:
database "nonexistent_db" does not exist [SQLSTATE 3D000]
The regression test provokes a REAL server error rather than constructing one,
because the bug was that the detail lives where Display does not look -- a
hand-built ForgeError::Storage would have passed throughout this file's
history. Verified to fail against the old one-liner.
9d4f91a6 · dbf3dbe6…
Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.