Repository: astral-sh/uv
File: crates/uv-client/src/error.rs (Rust)

Code before:
/// RFC 9457 Problem Details for HTTP APIs
///
/// This structure represents the standard format for machine-readable details
/// of errors in HTTP response bodies as defined in RFC 9457.
#[derive(Debug, Clone, Deserialize)]
pub struct ProblemDetails {
    /// A URI reference that identifies the problem type.
    /// When dereferenced, it SHOULD provide human-readable documentation for the problem type.
    #[serde(rename = "type", default = "default_problem_type")]
    pub problem_type: String,

    /// A short, human-readable summary of the problem type.
    pub title: Option<String>,

    /// The HTTP status code generated by the origin server for this occurrence of the problem.
    pub status: Option<u16>,

    /// A human-readable explanation specific to this occurrence of the problem.
    pub detail: Option<String>,

    /// A URI reference that identifies the specific occurrence of the problem.
    pub instance: Option<String>,

    /// Additional problem-specific extension fields
    #[serde(flatten)]
    pub extensions: std::collections::HashMap<String, serde_json::Value>,
}

/// Default problem type URI as per RFC 9457
fn default_problem_type() -> String {
    "about:blank".to_string()
}

impl ProblemDetails {
    /// Parse Problem Details from JSON bytes
    pub fn from_json(bytes: &[u8]) -> Result<Self, serde_json::Error> {
        serde_json::from_slice(bytes)
    }

    /// Get a human-readable description of the problem
    pub fn description(&self) -> String {
        if let Some(detail) = &self.detail {
            detail.clone()
        } else if let Some(title) = &self.title {
            title.clone()
        } else {
            format!("HTTP error {}", self.status.unwrap_or(0))
        }
    }
}


Review comment (suggestion):
serde will ignore unknown fields by default, so my 0.02c would be for removing this until we actually need to process extension fields. It'll also make the parsing slightly faster (not that that matters much on the error path):

```suggestion
```

(The tests should confirm that this works 🙂)

Code after:
/// RFC 9457 Problem Details for HTTP APIs
///
/// This structure represents the standard format for machine-readable details
/// of errors in HTTP response bodies as defined in RFC 9457.
#[derive(Debug, Clone, Deserialize)]
pub struct ProblemDetails {
    /// A URI reference that identifies the problem type.
    /// When dereferenced, it SHOULD provide human-readable documentation for the problem type.
    #[serde(rename = "type", default = "default_problem_type")]
    pub problem_type: String,

    /// A short, human-readable summary of the problem type.
    pub title: Option<String>,

    /// The HTTP status code generated by the origin server for this occurrence of the problem.
    pub status: Option<u16>,

    /// A human-readable explanation specific to this occurrence of the problem.
    pub detail: Option<String>,

    /// A URI reference that identifies the specific occurrence of the problem.
    pub instance: Option<String>,
}

/// Default problem type URI as per RFC 9457
#[inline]
fn default_problem_type() -> String {
    "about:blank".to_string()
}

impl ProblemDetails {
    /// Get a human-readable description of the problem
    pub fn description(&self) -> Option<String> {
        match self {
            Self {
                title: Some(title),
                detail: Some(detail),
                ..
            } => Some(format!("Server message: {title}, {detail}")),
            Self {
                title: Some(title), ..
            } => Some(format!("Server message: {title}")),
            Self {
                detail: Some(detail),
                ..
            } => Some(format!("Server message: {detail}")),
            Self {
                status: Some(status),
                ..
            } => Some(format!("HTTP error {status}")),
            _ => None,