Skip to main content

nexql_conn/
error.rs

1// SPDX-License-Identifier: GPL-3.0-only
2// Copyright (C) 2026 NexQL-OSS Team
3
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum ConnError {
8    #[error("no connection source resolved")]
9    NoSource,
10
11    #[error("profile not found: {0}")]
12    ProfileNotFound(String),
13
14    #[error("invalid connection URL: {0}")]
15    InvalidUrl(String),
16
17    #[error("config error: {0}")]
18    Config(String),
19
20    #[error("password_command failed: {0}")]
21    PasswordCommand(String),
22
23    #[error("password_command produced empty stdout")]
24    EmptyPasswordCommand,
25
26    #[error("env-file error: {0}")]
27    EnvFile(String),
28
29    #[error("pgpass error: {0}")]
30    PgPass(String),
31
32    #[error("pool error: {0}")]
33    Pool(String),
34
35    #[error("postgres error: {}", format_postgres_error(.0))]
36    Postgres(#[from] tokio_postgres::Error),
37
38    #[error("io error: {0}")]
39    Io(#[from] std::io::Error),
40}
41
42/// Human-readable Postgres message (detail/hint included when present).
43pub fn format_postgres_error(e: &tokio_postgres::Error) -> String {
44    if let Some(db_err) = e.as_db_error() {
45        let mut msg = db_err.message().to_string();
46        if let Some(detail) = db_err.detail() {
47            msg.push_str(&format!(" ({detail})"));
48        }
49        if let Some(hint) = db_err.hint() {
50            msg.push_str(&format!(" [hint: {hint}]"));
51        }
52        msg
53    } else {
54        e.to_string()
55    }
56}