Hmbown/CodeWhale · error · io::Error
Shared pet connection failed
Error message
Shared pet connection failed
What it means
This io::Error is returned by the shared-pet HTTP client in pet_watch/live.rs when the server responds with a non-success status. It carries the server's `error` message string (falling back to the generic text), and maps a 409 CONFLICT whose message does not mention 'storage' to ErrorKind::InvalidInput; all other failures map to ErrorKind::Other.
Solutions
- Read the error's message: it is the server's `error` field — fix the condition it names (e.g. retry later on a storage-related 409 conflict).
- Check connectivity/availability of the shared pet service before or after failure.
- Retry with backoff for transient 5xx; treat ErrorKind::InvalidInput (409 non-storage) as a request problem, not a retry.
- Fall back to local-only pet state when the shared connection fails.
Example fix
// before
let pet = shared.get(pet_id)?;
// after
let pet = match shared.get(pet_id) {
Ok(p) => p,
Err(e) if e.kind() == io::ErrorKind::Other => { log::warn!("shared pet unavailable: {e}"); local_pet() }
Err(e) => return Err(e),
}; Defensive patterns
Strategy: try-catch
Validate before calling
// optionally probe first let healthy = shared.get(health_path).is_ok();
Try / catch
match shared.post(url, &body) {
Err(e) if e.kind() == io::ErrorKind::Other => retry_with_backoff(),
Err(e) => return Err(e),
Ok(v) => Ok(v),
} Prevention
- Check server error messages, which are surfaced verbatim in the io::Error.
- Retry only transient (Other/5xx) failures, not InvalidInput (409 non-storage).
- Monitor shared-pet service health before batch operations.
When it happens
Trigger: Any request through the shared-pet API (request(), used by runner_request, public_request, get, post) that gets resp.success() == false — e.g. 409 conflict on concurrent pet updates, 4xx/5xx from the shared pet backend.
Common situations: Two clients writing the same shared pet state concurrently (409), shared-pet service outage returning 500, auth/permission rejection from the remote endpoint, offline network yielding a gateway error.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- building bundle fetch client failed
- bundle fetch failed with HTTP status
- bundle fetch request failed
- bundle redirects may not change URL scheme
- ${compactRuntimeError(response.status, body)}
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/bbcdad0cba183681.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/tui/pet_watch/live.rs:222
.map_err(io::Error::other)?;
let status = response.status();
let success = status.is_success();
let bound = if path == "/v1/export" {
super::persistence::MAX_EXPORT_BYTES
} else {
8 * 1024 * 1024
};
let mut bytes = Vec::new();
response.take(bound as u64 + 1).read_to_end(&mut bytes)?;
if bytes.len() > bound {
return Err(io::Error::other("Pet response exceeds its bound"));
}
let value: Value = serde_json::from_slice(&bytes)?;
if !success {
let message = value["error"]
.as_str()
.unwrap_or("Shared pet connection failed");
return Err(io::Error::new(
if status == reqwest::StatusCode::CONFLICT && !message.contains("storage") {
io::ErrorKind::InvalidInput
} else {
io::ErrorKind::Other
},
message,
));
}
Ok(value)
}
pub fn open_browser(&self) -> io::Result<()> {
let url = format!(
"http://127.0.0.1:{}/#{}",
self.descriptor.port, self.descriptor.token
);
webbrowser::open(&url).map_err(io::Error::other)
}
pub fn open_window(&self) -> io::Result<()> {View on GitHub (pinned to 73e0f67d83)