elsa-workflows/elsa-core · error · OutputConversionException
Output conversion failed during destination resolution
Error message
Output conversion failed during destination resolution
What it means
ActivityExecutionContext throws OutputConversionException with OutputConversionFailureStage.Resolution when resolving an output binding's destination returns null. The IOutputBindingDestinationResolver could not produce a destination for the given output, so the output value cannot be delivered. The exception names the converter, activity, output name, and memory block id for diagnosis.
Solutions
- Check the output's binding target (variable/output reference) exists in the definition and is in scope at the producing activity.
- Fix or implement the custom IOutputBindingDestinationResolver so it returns a valid destination or throws instead of null.
- Re-link the output in the designer to an existing variable so the destination resolves.
- Verify the resolvedOutputName and memory block id reported in the exception match an actually declared output.
Example fix
// before
class MyResolver : IOutputBindingDestinationResolver
{
public MemoryBlockReference? Resolve(...) => null; // triggers OutputConversionException
}
// after
class MyResolver : IOutputBindingDestinationResolver
{
public MemoryBlockReference? Resolve(...) =>
variable != null ? variable.MemoryBlockReference() : throw new InvalidOperationException($"Destination for output '{outputName}' not found");
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify the output binding target exists before execution
var target = outputBinding.Variable ?? (object?)outputBinding.Output;
if (target == null)
throw new InvalidOperationException($"Output '{outputName}' has no resolvable destination."); Type guard
static bool HasResolvableDestination(IOutputBindingDestinationResolver resolver, ActivityExecutionContext context, Output output) => resolver.Resolve(context, output) != null;
Try / catch
try { await workflowRunner.RunAsync(workflow); }
catch (OutputConversionException ex) when (ex.FailureStage == OutputConversionFailureStage.Resolution)
{
logger.LogError(ex, "Output '{Output}' on activity '{ActivityType}' has no resolvable destination", ex.OutputName, ex.ActivityType);
} Prevention
- Bind outputs only to variables/outputs declared in an enclosing scope.
- Re-link outputs in the designer after renaming or deleting target variables.
- Implement custom IOutputBindingDestinationResolvers to throw descriptive errors instead of returning null.
- Validate output bindings when importing definitions from external sources.
When it happens
Trigger: Delivering an output value where the output has a binding whose destination resolver returns null — e.g. an output bound to a variable/output reference that cannot be resolved in the current scope, or a custom IOutputBindingDestinationResolver returning null.
Common situations: Output bound to a variable that was renamed or deleted; custom destination resolvers returning null instead of throwing descriptive errors; output name mismatches between activity and binding configuration.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Output conversion failed during result validation
- Activity not found.
- Failed to convert an object of type
- AlterationFaultCodes.PlanNotFound
- No alterations found in the transient properties.
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/5a198ed61cd2d377.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.cs:800
// Also store the value in the workflow execution transient activity output register.
WorkflowExecutionContext.RecordActivityOutput(this, outputName, value);
return;
}
var descriptor = ActivityDescriptor.Outputs.FirstOrDefault(x => x.PropertyInfo?.Name == outputName);
descriptor ??= ActivityDescriptor.Outputs.FirstOrDefault(x => x.ValueGetter != null && ReferenceEquals(x.ValueGetter(Activity), output));
var resolvedOutputName = descriptor?.Name ?? outputName ?? ActivityOutputRegister.DefaultOutputName;
var sourceType = descriptor?.Type ?? GetOutputValueType(output.GetType()) ?? typeof(object);
// The activity output register always retains the activity's native value.
WorkflowExecutionContext.RecordActivityOutput(this, outputName, value);
var destinationResolver = GetRequiredService<IOutputBindingDestinationResolver>();
var destination = destinationResolver.Resolve(this, output);
if (destination == null)
{
throw new OutputConversionException(
output.Converter.Id,
OutputConversionFailureStage.Resolution,
Activity.Id,
Activity.Type,
resolvedOutputName,
output.MemoryBlockReference().Id,
sourceType,
null);
}
if (value == null)
{
if (!destination.AllowsNull)
{
throw new OutputConversionException(
output.Converter.Id,
OutputConversionFailureStage.ResultValidation,
Activity.Id,View on GitHub (pinned to fe9217bdfa)