From 51ee5d48e5e58aaee372479744d7d607f395d4f5 Mon Sep 17 00:00:00 2001 From: Mathias Date: Fri, 2 Oct 2026 17:47:13 +0200 Subject: [PATCH] feat(errkind): a database error is reduced to its SQLSTATE, never its message, which can quote a transcript value (fourth review) Co-Authored-By: Claude Sonnet 5.5 --- internal/errkind/errkind.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/internal/errkind/errkind.go b/internal/errkind/errkind.go index 74e9099..f1d719d 100644 --- a/internal/errkind/errkind.go +++ b/internal/errkind/errkind.go @@ -17,13 +17,20 @@ import ( // HTTPStatuser is implemented by errors that are a non-2xx answer from a service. type HTTPStatuser interface{ HTTPStatus() int } -// Of is the kind of err: "timeout", "canceled", "http_", "network", or "error". +// SQLStater is implemented by database errors that carry a SQLSTATE (pgx's PgError does). +// The five-character code is a fixed vocabulary; the error's message is not: Postgres quotes +// the offending value, which for a transcript row is transcript text. +type SQLStater interface{ SQLState() string } + +// Of is the kind of err: "timeout", "canceled", "http_", "sql_", "network", +// or "error". // It is empty for nil. func Of(err error) string { if err == nil { return "" } var hs HTTPStatuser + var ss SQLStater var ne net.Error switch { case errors.Is(err, context.DeadlineExceeded): @@ -32,6 +39,8 @@ func Of(err error) string { return "canceled" case errors.As(err, &hs): return fmt.Sprintf("http_%d", hs.HTTPStatus()) + case errors.As(err, &ss) && ss.SQLState() != "": + return "sql_" + ss.SQLState() case errors.As(err, &ne): if ne.Timeout() { return "timeout"