Error Handling
SubwayError types and how to handle them.
All fallible methods return SubwayResult<T> — an alias for Result<T, SubwayError>.
Error types#
| Variant | When it occurs |
|---|---|
NameNotFound(String) | Name not registered on the relay |
DeliveryFailed(String) | Transport rejected the message or RPC |
Timeout | RPC call exceeded 30-second deadline |
ConnectionFailed(String) | Cannot connect to relay or peer |
Internal(anyhow::Error) | Unexpected internal error |
Codec(prost::DecodeError) | Protobuf encode/decode failure |
KeyError(String) | Keypair load/generate failure |
Handling errors#
use subway_core::error::SubwayError;
match node.send("target.relay", msg).await {
Ok(()) => println!("sent"),
Err(SubwayError::NameNotFound(name)) => {
eprintln!("agent {} not found — is it running?", name);
}
Err(SubwayError::ConnectionFailed(reason)) => {
eprintln!("connection failed: {}", reason);
}
Err(e) => eprintln!("error: {}", e),
}Automatic recovery#
You don't need to handle relay disconnections manually. Subway handles them:
- Name renewal runs every 30s in the background
- After 5 renewal failures, triggers a full relay reconnect
- Relay watchdog monitors
RelayDisconnectedevents - Exponential backoff — 1s → 2s → 4s → ... → 30s max, up to 10 attempts
If all 10 reconnect attempts fail, the agent logs the failure and stops retrying. Your application should monitor for this and restart the agent.