use thiserror::Error;
#[derive(Debug, Error)]
pub enum ApiError {
#[error("{message}")]
Api { code: i64, message: String },
#[error("Network error: {0}")]
Network(#[from] reqwest::Error),
#[error("Invalid JSON response: {0}")]
InvalidJson(String),
#[error("Authentication required. Run `zilliz configure` or set ZILLIZ_API_KEY.")]
NoApiKey,
}
impl ApiError {
pub fn api(code: i64, mut message: String) -> Self {
let is_permission_denied =
message.contains("PermissionDenied") || message.to_lowercase().contains("permission deny");
if is_permission_denied {
message.push_str(
"\n\nThis may be a cluster plan restriction. \
Some operations (user/role management, multi-database) \
are only available on Dedicated clusters.",
);
}
if let Some(hint) =
crate::cli::error_hints::get_error_hint(None, code, &message)
{
message.push_str(&format!("\nHint: {}", hint));
}
Self::Api { code, message }
}
pub fn non_json_response(status: reqwest::StatusCode, content_type: &str) -> Self {
let hint = match status.as_u16() {
401 | 403 => "Invalid or expired API key. Run `zilliz configure` to update.",
404 => "API endpoint not found. Check your cluster endpoint.",
502..=504 => "Service temporarily unavailable. Try again later.",
_ => "Server returned a non-JSON response.",
};
let mut message = format!(
"HTTP {} ({}). {}",
status.as_u16(),
content_type,
hint
);
if let Some(extra_hint) =
crate::cli::error_hints::get_error_hint(Some(status.as_u16()), 0, &message)
{
message.push_str(&format!("\nHint: {}", extra_hint));
}
Self::Api {
code: status.as_u16() as i64,
message,
}
}
}