{"record":{"id":"fb25c0277c016795","repo":"OrchardCMS/OrchardCore","slug":"workflowexecutioncontext-missing-while-invoking-signal-url","errorCode":null,"errorMessage":"WorkflowExecutionContext missing while invoking 'signal_url'","messagePattern":"WorkflowExecutionContext missing while invoking 'signal_url'","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/OrchardCore.Modules/OrchardCore.Workflows/Http/Liquid/SignalUrlFilter.cs","lineNumber":31,"sourceCode":"{\n    private readonly IUrlHelperFactory _urlHelperFactory;\n    private readonly ISecurityTokenService _securityTokenService;\n\n    public SignalUrlFilter(IUrlHelperFactory urlHelperFactory, ISecurityTokenService securityTokenService)\n    {\n        _urlHelperFactory = urlHelperFactory;\n        _securityTokenService = securityTokenService;\n    }\n\n    public ValueTask<FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext ctx)\n    {\n        var urlHelper = _urlHelperFactory.GetUrlHelper(ctx.ViewContext);\n\n        var workflowContextValue = ctx.GetValue(\"Workflow\");\n\n        if (workflowContextValue.IsNil())\n        {\n            throw new ArgumentException(\"WorkflowExecutionContext missing while invoking 'signal_url'\");\n        }\n\n        var workflowContext = (WorkflowExecutionContext)workflowContextValue.ToObjectValue();\n        var signalName = input.ToStringValue();\n        var payload = string.IsNullOrWhiteSpace(workflowContext.CorrelationId)\n            ? SignalPayload.ForWorkflow(signalName, workflowContext.WorkflowId)\n            : SignalPayload.ForCorrelation(signalName, workflowContext.CorrelationId);\n\n        var token = _securityTokenService.CreateToken(payload, TimeSpan.FromDays(7));\n        var urlValue = StringValue.Create(urlHelper.Action(\"Trigger\", \"HttpWorkflow\", new { area = \"OrchardCore.Workflows\", token }));\n\n        return ValueTask.FromResult<FluidValue>(urlValue);\n    }\n}\n","sourceCodeStart":13,"sourceCodeEnd":46,"githubUrl":"https://github.com/OrchardCMS/OrchardCore/blob/4306c0717fe573f6fca1b4955909ddab6a192807/src/OrchardCore.Modules/OrchardCore.Workflows/Http/Liquid/SignalUrlFilter.cs#L13-L46","documentation":"The signal_url Liquid filter builds a URL that signals a running workflow, so it requires the current WorkflowExecutionContext (exposed to Liquid as the 'Workflow' variable). SignalUrlFilter checks ctx.GetValue(\"Workflow\") and throws ArgumentException when it is nil, because without a workflow context there is no correlation ID or workflow ID to embed in the signal URL.","triggerScenarios":"Calling the 'signal_url' filter in a Liquid template rendered outside a workflow execution context — e.g. in an email notification template, a page/view, a content item body, or any template where the 'Workflow' local variable was not supplied. Also occurs if the workflow engine variable was renamed or not passed to the template.","commonSituations":"Using signal_url in Liquid Workflows Email templates evaluated for activities that lack a Workflow scope; using the filter in site-wide templates like layouts or notification templates not tied to a workflow; typos such as lowercase 'workflow' instead of 'Workflow'.","solutions":["Use the signal_url filter only inside templates executed within a workflow (where the 'Workflow' variable is provided), such as activity-attached Liquid templates.","If you need a signal URL outside a workflow, build it manually with the workflow ID/correlation ID via Url.Action on the Workflow Http signal endpoints instead of the filter.","Verify the template really receives the Workflow variable; check how the template is invoked (which activity/template host) and pass WorkflowExecutionContext as 'Workflow' if you control the rendering.","Replace signal_url with a static URL to the signal endpoint and supply the workflow id/correlation id as route values in a context where you know them."],"exampleFix":"// before (outside any workflow context)\n// {{ 'ApprovalReceived' | signal_url }}\n// after (guard or build manually)\n// {% if Workflow %}{{ 'ApprovalReceived' | signal_url }}{% else %}/workflows/signal{% endif %}","handlingStrategy":"type-guard","validationCode":"// in the Liquid template, guard before using the filter\n// {% if Workflow %}{{ 'Name' | signal_url }}{% else %}{{ '/workflows/signal' }}{% endif %}","typeGuard":"// C# equivalent before rendering\nobject workflowValue = context.TryGetValue(\"Workflow\", out var w) ? w : null;\nbool hasWorkflow = workflowValue is not null and not Fluid.Values.NilValue.Instance and not Fluid.Values.EmptyValue.Instance;","tryCatchPattern":"try { url = renderedTemplate; }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"signal_url\"))\n{ logger.LogWarning(\"signal_url used outside a workflow context\"); url = fallbackUrl; }","preventionTips":["Only use signal_url in templates rendered during workflow execution (activity templates, workflow emails)","Do not use signal_url in site-wide layouts, pages, or content bodies","Check the variable name is exactly 'Workflow' (case-sensitive)","For non-workflow contexts, construct the signal endpoint URL manually with known ids"],"tags":["workflows","liquid","missing-context","orchardcore"],"backgroundTag":"missing-required-argument","analyzedSha":"4306c0717fe573f6fca1b4955909ddab6a192807","analyzedAt":"2026-09-13T17:41:05.024Z","contentChangedAt":"2026-09-13T17:41:05.024Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}