clockworklabs/SpacetimeDB · error · Exception
e.ToString()
Error message
e.ToString()
What it means
Result<T,E> is the SDK's error-handling type: Ok carries a value, Err carries an error. UnwrapOrThrow returns the Ok payload; on an Err whose error object is non-null it throws a plain Exception whose message is e.ToString() (the error's own string form). An Err with a null error object instead throws InvalidOperationException.
Source
Thrown at crates/bindings-csharp/BSATN.Runtime/Builtins.cs:658
public TResult Match<TResult>(Func<T, TResult> onOk, Func<E, TResult> onErr) =>
this switch
{
OkR(var v) => onOk(v),
ErrR(var e) => onErr(e),
_ => throw new InvalidOperationException("Unknown Result variant."),
};
public static Result<T, E> Ok(T value) => new OkR(value);
public static Result<T, E> Err(E error) => new ErrR(error);
public T UnwrapOrThrow()
{
return this switch
{
OkR(var v) => v,
ErrR(var e) when e is not null => throw new Exception(e.ToString()),
ErrR(_) => throw new InvalidOperationException(
"Result failed without an error object."
),
_ => throw new InvalidOperationException("Unknown Result variant."),
};
}
public T UnwrapOr(T defaultValue) =>
this switch
{
OkR(var v) => v,
_ => defaultValue,
};
public T UnwrapOrElse(Func<E, T> f) =>
this switch
{
OkR(var v) => v,View on GitHub (pinned to 6dee26c6ef)
Solutions
- Check the Result variant before unwrapping, and handle the Err payload explicitly
- If a fallback is acceptable, use result.UnwrapOr(defaultValue) which never throws
- When you must unwrap, catch the Exception and read its Message — it is the Err value's ToString()
- Fix the underlying condition the error object reports (usually a module- or server-side rejection)
Example fix
// before var value = result.UnwrapOrThrow(); // throws Exception with e.ToString() // after var value = result.UnwrapOr(fallback); // no throw; fallback used on Err
Defensive patterns
Strategy: try-catch
Try / catch
try
{
return result.UnwrapOrThrow();
}
catch (InvalidOperationException)
{
// Err with a null error object: log and rethrow as a domain error
throw;
}
catch (Exception ex)
{
// Message is the Err value's ToString(): log it for diagnosis
logger.LogError("Result failed: {Message}", ex.Message);
throw;
} Prevention
- Prefer explicit variant checks over blind UnwrapOrThrow
- Use UnwrapOr(defaultValue) when a fallback is acceptable
- Log the Err payload where the Result is produced, not only where it is unwrapped
- Treat the thrown message as the module/server rejection reason and fix the root cause
When it happens
Trigger: Calling UnwrapOrThrow on a Result produced by a failed operation — a rejected reducer call or client API that returned Err(error) — without first checking the variant.
Common situations: Prototypes or tests unwrapping results that actually contain business errors (validation failure, permission denied, module rejection); assuming success after an async call without inspecting the outcome.
Related errors
- Argument must be a I128
- Argument must be a I256
- Tag {tag} is out of range of enum {typeof(T).Name}
- Value {value} is out of range for enum {typeof(T).Name}
- Cannot serialize a null string as BSATN String. To serialize
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/dbd66d8cf025ba2c.
Report an issue: GitHub.