Errors
Every SDK operation throws OpenShellException. Switch on its Kind, an OpenShellErrorKind. Gateway errors map from the gRPC status; the last four kinds come from the client itself.
| Kind | Meaning | gRPC status |
|---|---|---|
NotFound |
The resource does not exist. | NOT_FOUND |
AlreadyExists |
The resource already exists. | ALREADY_EXISTS |
PermissionDenied |
The caller is authenticated but not allowed. | PERMISSION_DENIED |
Unauthenticated |
Credentials are missing or invalid. | UNAUTHENTICATED |
InvalidArgument |
A request argument was rejected. | INVALID_ARGUMENT, OUT_OF_RANGE |
Conflict |
Optimistic concurrency or an invalid state transition. | ABORTED, FAILED_PRECONDITION |
Unavailable |
The gateway is temporarily unavailable. | UNAVAILABLE |
DeadlineExceeded |
The call or a wait exceeded its deadline. | DEADLINE_EXCEEDED |
Cancelled |
The call was cancelled by the gateway. | CANCELLED |
Unimplemented |
The gateway does not implement the operation (or a field it needs). | UNIMPLEMENTED |
Internal |
The gateway reported an internal error. | INTERNAL, DATA_LOSS |
Unknown |
Anything else. | UNKNOWN, RESOURCE_EXHAUSTED, and other codes |
InvalidConfig |
The client was configured inconsistently or unsafely. | (client side) |
Tls |
TLS material could not be loaded, for example a registered gateway's mTLS bundle. | (client side) |
Connect |
The gateway could not be reached. A connection failure during a call surfaces as Unavailable. |
(client side) |
Auth |
Credentials could not be obtained or refreshed, for example an OIDC failure. | (client side) |
The shortcuts IsNotFound, IsAlreadyExists, IsConflict, and IsTransient (Unavailable or DeadlineExceeded) cover the common cases, and GrpcStatusCode exposes the underlying gRPC status when there is one.
try
{
await client.Sandboxes.GetAsync("missing");
}
catch (OpenShellException e) when (e.IsNotFound)
{
Console.WriteLine("no such sandbox");
}
catch (OpenShellException e) when (e.IsTransient)
{
// Unavailable or DeadlineExceeded, after the retries ran out.
Console.WriteLine($"gateway unavailable: {e.Message}");
}
catch (OpenShellException e)
{
Console.WriteLine($"{e.Kind} (gRPC {e.GrpcStatusCode}): {e.Message}");
}
Cancelling a call through its own CancellationToken throws OperationCanceledException, not OpenShellException. Arguments that are invalid before anything is sent (a null or empty name, an empty command) throw ArgumentException.
Error details
When the gateway attaches structured details (google.rpc.Status), the exception exposes them:
- ErrorInfo: a stable
Reason, aDomain, and metadata. Match onReasonrather than on the message. - FieldViolations: the request fields that were rejected, and why.
- RetryDelay: the delay the gateway suggested before trying again. It says nothing about whether repeating a mutation is safe; see Retries.
try
{
await client.Sandboxes.CreateAsync("Bad Name!", new SandboxSpec { Image = "img" });
}
catch (OpenShellException e) when (e.Kind == OpenShellErrorKind.InvalidArgument)
{
foreach (var violation in e.FieldViolations)
{
Console.WriteLine($"{violation.Field}: {violation.Description}");
}
if (e.ErrorInfo is { } info)
{
Console.WriteLine($"{info.Domain}/{info.Reason}");
}
}
The SDK ignores details whose envelope does not match the call's status, so a mismatched trailer cannot rewrite the error.
Errors in raw calls
Calls made through OpenShellClient.Raw throw the gRPC RpcException instead; see Raw gRPC access.