clockworklabs/SpacetimeDB · error · InvalidOperationException
Result failed without an error object.
Error message
Result failed without an error object.
What it means
Result<T,E>.UnwrapOrThrow expects the Err variant to carry a non-null error object; when it finds ErrR(null) there is nothing to surface, so it throws InvalidOperationException. This guards against silently reporting an empty failure and usually points at a producer that constructed Result.Err(null) - typically a null message, exception, or nullable reference-typed error.
Source
Thrown at crates/bindings-csharp/BSATN.Runtime/Builtins.cs:659
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,
ErrR(var e) => f(e),View on GitHub (pinned to 524b4487d9)
Solutions
- Find the code constructing the Err value and guarantee a non-null error: Result<T,E>.Err(error ?? fallbackError)
- Check the variant with Match/UnwrapOr before unwrapping instead of calling UnwrapOrThrow blind
- If E is a string, use the exception's full ToString() or a constant message rather than ex.Message alone
- Enable nullable reference types so Err(null) is a compile warning at the producer
Example fix
// before return Result<string, string>.Err(ex.Message); // ex.Message may be null ... var v = result.UnwrapOrThrow(); // throws 'Result failed without an error object.' // after return Result<string, string>.Err(ex.ToString()); ... var v = result.UnwrapOrThrow();
Defensive patterns
Strategy: validation
Validate before calling
// Inspect before unwrapping; never let a null error reach UnwrapOrThrow.
var payload = result.Match(
onOk: v => (Value: v, Error: (string?)null),
onErr: e => (Value: default(T), Error: e?.ToString() ?? "unknown error"));
if (payload.Error is null) { /* use payload.Value */ } Try / catch
try { value = result.UnwrapOrThrow(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("without an error object"))
{ /* producer bug: Err was constructed with null; log and fail loudly */ } Prevention
- Never construct Result<T,E>.Err(null) - coalesce to a fallback error first
- Enable nullable reference types so null errors warn at the construction site
- Prefer Match/UnwrapOr over UnwrapOrThrow when the producer is not fully under your control
When it happens
Trigger: Result<T,string>.Err(null!); building Err from ex.Message where the exception has no message; an API contract where E is a nullable/optional error type and callers pass default; default(Result<T,E>) misuse.
Common situations: Wrapping third-party exceptions with empty messages into Result errors; FFI boundaries returning null error payloads; generics where E is a reference type and null sneaks through unchecked nullable annotations.
Related errors
- never types are not yet supported in C# output
- Unsupported --dotnet-version {version}. Supported values: 8,
- --namespace is only supported with --lang csharp
- --dotnet-version is only supported for C# projects (--lang c
- --native-aot is only supported for C# projects (--lang cshar
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/6ea70f3dfd9a382e.
Report an issue: GitHub.