{"record":{"id":"2a1bf9e90a5db002","repo":"elsa-workflows/elsa-core","slug":"cannot-access-value-on-a-failed-result-check-issuccess-first","errorCode":null,"errorMessage":"Cannot access Value on a failed result. Check IsSuccess first or use ValueOrDefault.","messagePattern":"Cannot access Value on a failed result\\. Check IsSuccess first or use ValueOrDefault\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Common/Models/Result.cs","lineNumber":21,"sourceCode":"/// <summary>\n/// A strongly typed monad that runs either the <see cref=\"OnSuccess\"/> or <see cref=\"OnFailure\"/> lambda, depending on whether or not the operation succeeded.\n/// </summary>\npublic class Result<T>(bool success, T? value, Exception? exception)\n{\n    /// <summary>\n    /// True if the conversion succeeded, false otherwise.\n    /// </summary>\n    public bool IsSuccess { get; } = success;\n\n    /// <summary>\n    /// The result value. Throws an exception if accessed when the result is a failure.\n    /// </summary>\n    public T Value\n    {\n        get\n        {\n            if (!IsSuccess)\n                throw new InvalidOperationException(\"Cannot access Value on a failed result. Check IsSuccess first or use ValueOrDefault.\", Exception);\n            return value!;\n        }\n    }\n\n    /// <summary>\n    /// The result value, or null/default if the result is a failure. Useful when null is a valid success value.\n    /// </summary>\n    public T? ValueOrDefault => value;\n\n    /// <summary>\n    /// Any exception that may have occurred during the operation.\n    /// </summary>\n    public Exception? Exception { get; } = exception;\n\n    /// <summary>\n    /// Runs the provided delegate if the result is successful.\n    /// </summary>\n    public Result<T> OnSuccess(Action<T> successHandler)","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Common/Models/Result.cs#L3-L39","documentation":"Result<T> models success/failure. The Value getter only exists for successful results; accessing it on a failed result throws this InvalidOperationException, with the original exception attached as innerException.","triggerScenarios":"Reading result.Value without checking result.IsSuccess on a failed Result<T>, e.g. after an operation that returns a failure instead of throwing.","commonSituations":"Ignoring the IsSuccess flag in calling code; assuming an operation always succeeds; refactors that changed a throwing API into a Result-returning API without updating callers.","solutions":["Check result.IsSuccess (or IsFailure) before accessing Value.","Use result.ValueOrDefault when a default is acceptable for failures.","Switch to a Match/switch expression handling both outcomes.","Inspect result.Exception via the inner exception to diagnose the underlying failure."],"exampleFix":"// before\nvar value = result.Value;\n// after\nif (!result.IsSuccess) return HandleFailure(result.Exception);\nvar value = result.Value;","handlingStrategy":"type-guard","validationCode":"if (result.IsFailure)\n    return HandleFailure(result.Exception);","typeGuard":"bool TryGetValue<T>(Result<T> result, out T? value) { value = result.IsSuccess ? result.Value : default; return result.IsSuccess; }","tryCatchPattern":"try { value = result.Value; }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"failed result\")) { value = fallback; }","preventionTips":["Always branch on IsSuccess/IsFailure before touching Value","Prefer ValueOrDefault or Match over raw Value access","Enable nullable annotations so default-value paths are explicit"],"tags":["result-pattern","dotnet","api-misuse"],"backgroundTag":"invalid-state-transition","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}