elsa-workflows/elsa-core · error · InvalidCastException

Cannot convert null to non-nullable type

Error message

Cannot convert null to non-nullable type {typeof(T).FullName}.

What it means

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.

Solutions

  1. Request a nullable type (int? / Guid?) so a missing output yields null
  2. Verify the activity executed successfully and its ID is correct
  3. Check the value for null before conversion using the underlying result API
  4. Guard execution with try/catch around InvalidCastException

Example fix

// before
var count = result.GetActivityOutput<int>("Counter");
// after
var count = result.GetActivityOutput<int?>("Counter") ?? 0;
Defensive patterns

Strategy: type-guard

Validate before calling

var raw = result.GetActivityOutput<object?>("Counter"); if (raw is null) { /* handle missing output */ }

Type guard

T? GetOutputOrNull<T>(IWorkflowExecutionResult r, string id) where T : struct => r.GetActivityOutput<T?>(id);

Try / catch

try { count = result.GetActivityOutput<int>("Counter"); } catch (InvalidCastException ex) when (ex.Message.Contains("non-nullable")) { count = 0; }

Prevention

When it happens

Trigger: Calling workflowResult.GetActivityOutput<int>("MyActivity") when the activity produced no output (null) — only for non-nullable T such as int or Guid.

Common situations: 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.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/dbc19588b1e18fe3. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Workflows.Core/Extensions/WorkflowExecutionResultExtensions.cs:21

namespace Elsa.Workflows;

public static class WorkflowExecutionResultExtensions
{
    public static T GetActivityOutput<T>(this RunWorkflowResult result, IActivity activity, string? outputName = null)
    {
        var value = result.WorkflowExecutionContext.GetOutputByActivityId(activity.Id, outputName);

        // If the value is already of the requested type, return it directly.
        if (value is T tValue)
            return tValue;

        // Handle nulls for reference/nullable types.
        if (value is null)
        {
            // If T is a reference type or nullable, default(T) is fine.
            // Otherwise, this is a runtime error.
            return default(T) is null ? default! : throw new InvalidCastException($"Cannot convert null to non-nullable type {typeof(T).FullName}.");
        }

        // Try to convert using System.Convert when possible (handles numeric casts like Double -> Int32).
        try
        {
            var targetType = typeof(T);

            // Unwrap nullable<T> to its underlying type for conversion.
            var underlyingType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            var converted = Convert.ChangeType(value, underlyingType, System.Globalization.CultureInfo.InvariantCulture);

            // If T is nullable and we converted to the underlying type, just cast.
            return (T)converted!;
        }
        catch (Exception ex)
        {
            throw new InvalidCastException($"Unable to convert value of type '{value.GetType().FullName}' to type '{typeof(T).FullName}'.", ex);

View on GitHub (pinned to fe9217bdfa)