{"record":{"id":"dbc19588b1e18fe3","repo":"elsa-workflows/elsa-core","slug":"cannot-convert-null-to-non-nullable-type-typeof-t-fullname","errorCode":null,"errorMessage":"Cannot convert null to non-nullable type {typeof(T).FullName}.","messagePattern":"Cannot convert null to non-nullable type (.+?)\\.","errorType":"exception","errorClass":"InvalidCastException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Workflows.Core/Extensions/WorkflowExecutionResultExtensions.cs","lineNumber":21,"sourceCode":"\nnamespace Elsa.Workflows;\n\npublic static class WorkflowExecutionResultExtensions\n{\n    public static T GetActivityOutput<T>(this RunWorkflowResult result, IActivity activity, string? outputName = null)\n    {\n        var value = result.WorkflowExecutionContext.GetOutputByActivityId(activity.Id, outputName);\n\n        // If the value is already of the requested type, return it directly.\n        if (value is T tValue)\n            return tValue;\n\n        // Handle nulls for reference/nullable types.\n        if (value is null)\n        {\n            // If T is a reference type or nullable, default(T) is fine.\n            // Otherwise, this is a runtime error.\n            return default(T) is null ? default! : throw new InvalidCastException($\"Cannot convert null to non-nullable type {typeof(T).FullName}.\");\n        }\n\n        // Try to convert using System.Convert when possible (handles numeric casts like Double -> Int32).\n        try\n        {\n            var targetType = typeof(T);\n\n            // Unwrap nullable<T> to its underlying type for conversion.\n            var underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType;\n\n            var converted = Convert.ChangeType(value, underlyingType, System.Globalization.CultureInfo.InvariantCulture);\n\n            // If T is nullable and we converted to the underlying type, just cast.\n            return (T)converted!;\n        }\n        catch (Exception ex)\n        {\n            throw new InvalidCastException($\"Unable to convert value of type '{value.GetType().FullName}' to type '{typeof(T).FullName}'.\", ex);","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Workflows.Core/Extensions/WorkflowExecutionResultExtensions.cs#L3-L39","documentation":"GetActivityOutput<T> converts an activity output value to T; when the value is null and T is a non-nullable value type (default(T) is not null), it throws InvalidCastException. Reference-type and Nullable<T> targets tolerate null via default. This surfaces type-unsafety rather than silently coercing null to a bogus value.","triggerScenarios":"Calling workflowResult.GetActivityOutput<int>(\"MyActivity\") when the activity produced no output (null) — only for non-nullable T such as int or Guid.","commonSituations":"Activity faulted or was skipped so its output was never set; querying the wrong activity ID; using int instead of int? for an optional output.","solutions":["Request a nullable type (int? / Guid?) so a missing output yields null","Verify the activity executed successfully and its ID is correct","Check the value for null before conversion using the underlying result API","Guard execution with try/catch around InvalidCastException"],"exampleFix":"// before\nvar count = result.GetActivityOutput<int>(\"Counter\");\n// after\nvar count = result.GetActivityOutput<int?>(\"Counter\") ?? 0;","handlingStrategy":"type-guard","validationCode":"var raw = result.GetActivityOutput<object?>(\"Counter\"); if (raw is null) { /* handle missing output */ }","typeGuard":"T? GetOutputOrNull<T>(IWorkflowExecutionResult r, string id) where T : struct => r.GetActivityOutput<T?>(id);","tryCatchPattern":"try { count = result.GetActivityOutput<int>(\"Counter\"); } catch (InvalidCastException ex) when (ex.Message.Contains(\"non-nullable\")) { count = 0; }","preventionTips":["Use Nullable<T> for outputs that may legitimately be missing","Confirm the activity executed successfully before reading its output"],"tags":["type-cast","null","invalidcast"],"backgroundTag":"type-mismatch","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}