diff --git a/server-rs/crates/platform-tripo/src/common/client.rs b/server-rs/crates/platform-tripo/src/common/client.rs index d08f25ff9..5e6bb20c8 100644 --- a/server-rs/crates/platform-tripo/src/common/client.rs +++ b/server-rs/crates/platform-tripo/src/common/client.rs @@ -110,15 +110,22 @@ impl TripoProviderClient { .map_err(|_elapsed| artifact_stall_error(task_id, self.artifact_stall_timeout))? .map_err(|error| TripoError::Request { message: format!( - "artifact download transport failure for task {task_id}: {}", - transport_error_kind(&error) + "artifact download transport failure for task {task_id}: {} from {} ({})", + transport_error_kind(&error), + url.redacted(), + transport_error_source(&error), ), status: None, })?; let status = response.status(); if !status.is_success() { return Err(TripoError::Request { - message: format!("artifact download failed for task {task_id}"), + message: format!( + "artifact download failed for task {task_id}: {} {} ({})", + status.as_u16(), + status.canonical_reason().unwrap_or("unknown status"), + url.redacted(), + ), status: Some(status.as_u16()), }); } @@ -183,6 +190,13 @@ fn transport_error_kind(error: &reqwest::Error) -> &'static str { } } +/// reqwest 的 `Display` 会带上完整 URL(含签名参数),排障只取 source 链。 +fn transport_error_source(error: &reqwest::Error) -> String { + std::error::Error::source(error) + .map(|source| source.to_string()) + .unwrap_or_else(|| "no source detail".to_string()) +} + #[cfg(test)] mod tests { use std::net::SocketAddr;