{"record":{"id":"918b13746e679113","repo":"elsa-workflows/elsa-core","slug":"unable-to-convert-value-of-type-value-gettype-fullname-to","errorCode":null,"errorMessage":"Unable to convert value of type '{value.GetType().FullName}' to type '{typeof(T).FullName}'.","messagePattern":"Unable to convert value of type '(.+?)' to type '(.+?)'\\.","errorType":"exception","errorClass":"InvalidCastException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Workflows.Core/Extensions/WorkflowExecutionResultExtensions.cs","lineNumber":39,"sourceCode":"            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);\n        }\n    }\n}","sourceCodeStart":21,"sourceCodeEnd":42,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Workflows.Core/Extensions/WorkflowExecutionResultExtensions.cs#L21-L42","documentation":"GetActivityOutput<T> attempts conversion (including System.Convert for numeric widening) and wraps any failure in InvalidCastException with both source and target type names. It preserves the inner exception as the cause. This happens after the null check, i.e. a value existed but could not be converted.","triggerScenarios":"Retrieving an output as T where the stored value's runtime type has no conversion to T, e.g. GetActivityOutput<string>(\"Timer\") when the output is a DateTimeOffset, or incompatible numeric/object casts that Convert.ChangeType rejects.","commonSituations":"Assuming the wrong output type after changing an activity; deserialized output arriving as JsonElement/string while code expects a typed object; culture-dependent parse failures inside Convert.","solutions":["Match T to the actual output type declared by the activity (check the activity's Output property type)","Inspect the inner exception to see the exact conversion failure","Convert explicitly in user code (e.g. DateTime.Parse) before/instead of the generic cast","Use object as T and cast manually with checks"],"exampleFix":"// before\nvar ts = result.GetActivityOutput<string>(\"Timer\");\n// after\nvar ts = result.GetActivityOutput<DateTimeOffset>(\"Timer\").ToString(\"O\");","handlingStrategy":"try-catch","validationCode":"var raw = result.GetActivityOutput<object?>(id); if (raw is T typed) { /* use typed */ }","typeGuard":"bool TryGetOutput<T>(IWorkflowExecutionResult r, string id, out T? value) { var raw = r.GetActivityOutput<object?>(id); if (raw is T t) { value = t; return true; } value = default; return false; }","tryCatchPattern":"try { value = result.GetActivityOutput<T>(id); } catch (InvalidCastException ex) { logger.LogError(ex, \"Output {Id} not convertible to {Type}\", id, typeof(T)); }","preventionTips":["Match T to the activity's declared output type","Use the object-typed overload plus pattern matching for flexible retrieval"],"tags":["type-cast","invalidcast","type-mismatch"],"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"}