{"record":{"id":"6ea70f3dfd9a382e","repo":"clockworklabs/SpacetimeDB","slug":"result-failed-without-an-error-object","errorCode":null,"errorMessage":"Result failed without an error object.","messagePattern":"Result failed without an error object\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/BSATN.Runtime/Builtins.cs","lineNumber":659,"sourceCode":"    public TResult Match<TResult>(Func<T, TResult> onOk, Func<E, TResult> onErr) =>\n        this switch\n        {\n            OkR(var v) => onOk(v),\n            ErrR(var e) => onErr(e),\n            _ => throw new InvalidOperationException(\"Unknown Result variant.\"),\n        };\n\n    public static Result<T, E> Ok(T value) => new OkR(value);\n\n    public static Result<T, E> Err(E error) => new ErrR(error);\n\n    public T UnwrapOrThrow()\n    {\n        return this switch\n        {\n            OkR(var v) => v,\n            ErrR(var e) when e is not null => throw new Exception(e.ToString()),\n            ErrR(_) => throw new InvalidOperationException(\n                \"Result failed without an error object.\"\n            ),\n            _ => throw new InvalidOperationException(\"Unknown Result variant.\"),\n        };\n    }\n\n    public T UnwrapOr(T defaultValue) =>\n        this switch\n        {\n            OkR(var v) => v,\n            _ => defaultValue,\n        };\n\n    public T UnwrapOrElse(Func<E, T> f) =>\n        this switch\n        {\n            OkR(var v) => v,\n            ErrR(var e) => f(e),","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-csharp/BSATN.Runtime/Builtins.cs#L641-L677","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nreturn Result<string, string>.Err(ex.Message); // ex.Message may be null\n...\nvar v = result.UnwrapOrThrow(); // throws 'Result failed without an error object.'\n\n// after\nreturn Result<string, string>.Err(ex.ToString());\n...\nvar v = result.UnwrapOrThrow();","handlingStrategy":"validation","validationCode":"// Inspect before unwrapping; never let a null error reach UnwrapOrThrow.\nvar payload = result.Match(\n    onOk: v => (Value: v, Error: (string?)null),\n    onErr: e => (Value: default(T), Error: e?.ToString() ?? \"unknown error\"));\nif (payload.Error is null) { /* use payload.Value */ }","typeGuard":null,"tryCatchPattern":"try { value = result.UnwrapOrThrow(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"without an error object\"))\n{ /* producer bug: Err was constructed with null; log and fail loudly */ }","preventionTips":["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"],"tags":["csharp","result","unwrap","null-error","error-handling"],"backgroundTag":"result-unwrap-null-error","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}