OrchardCMS/OrchardCore · error · ArgumentException
HttpRequest missing while invoking 'switch_culture_url'
Error message
HttpRequest missing while invoking 'switch_culture_url'
What it means
The switch_culture_url Liquid filter builds a URL that redirects to the localized version of the current content. It needs the current HttpRequest to resolve the route; when HttpContext or its Request is unavailable (e.g. rendering a Liquid template outside an HTTP request) it throws ArgumentException.
Solutions
- Only use switch_culture_url in templates rendered during an HTTP request.
- In background flows, build the URL explicitly with IUrlHelper/LinkGenerator using a configured base URL instead of the filter.
- Guard the template with an http-context availability check, or supply an IHttpContextAccessor-backed DefaultHttpContext.
- Wrap rendering in try/catch and fall back to a plain culture-neutral link.
Example fix
// before
var url = await template.RenderAsync(...); // template uses switch_culture_url, no HttpContext
// after
var url = _linkGenerator.GetPathByRouteName("RedirectToLocalizedContent", new { area = "OrchardCore.ContentLocalization", culture = "fr" }); Defensive patterns
Strategy: fallback
Validate before calling
{% if http_context %}{{ content | switch_culture_url: 'fr' }}{% else %}/fr{{ content | display_text }}{% endif %} Type guard
static bool HasRequest(LiquidTemplateContext ctx) => ctx.ViewContext?.HttpContext?.Request is not null;
Try / catch
try { url = await filter.ProcessAsync(input, args, ctx); }
catch (ArgumentException ex) when (ex.Message.Contains("switch_culture_url"))
{ url = fallbackPath; logger.LogDebug("switch_culture_url used outside HTTP context; using fallback"); } Prevention
- Use HTTP-context-dependent filters only in request-scoped templates
- In emails/background jobs, use LinkGenerator with an absolute base URL
- Provide a DefaultHttpContext when unit-testing Liquid templates
- Document which filters require an active request
When it happens
Trigger: Using {{ content | switch_culture_url: 'fr' }} in a template rendered without a ViewContext/HttpContext — background email/liquid templating jobs, workflow activities without an HTTP context, or unit tests rendering templates directly.
Common situations: Sending Liquid-rendered notification emails from a background task; rendering templates in workflow scheduled events; running template previews in a console/hosted service.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- The ' ' shape has been called recursively more than times.
- Incorrect value type assigned to a tag.
- Cannot override href with other properties
- Format of the link cannot be determined based on the…
- page_title tag requires a segment argument
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/b1b4a98cc81f5577.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore.Modules/OrchardCore.ContentLocalization/Liquid/SwitchCultureUrlFilter.cs:26
namespace OrchardCore.ContentLocalization.Liquid;
public class SwitchCultureUrlFilter : ILiquidFilter
{
private readonly IUrlHelperFactory _urlHelperFactory;
private readonly IHttpContextAccessor _httpContextAccessor;
public SwitchCultureUrlFilter(IUrlHelperFactory urlHelperFactory, IHttpContextAccessor httpContextAccessor)
{
_urlHelperFactory = urlHelperFactory;
_httpContextAccessor = httpContextAccessor;
}
public ValueTask<FluidValue> ProcessAsync(FluidValue input, FilterArguments arguments, LiquidTemplateContext context)
{
var urlHelper = _urlHelperFactory.GetUrlHelper(context.ViewContext);
var request = _httpContextAccessor.HttpContext?.Request
?? throw new ArgumentException("HttpRequest missing while invoking 'switch_culture_url'");
var targetCulture = input.ToStringValue();
var url = urlHelper.RouteUrl("RedirectToLocalizedContent",
new
{
area = "OrchardCore.ContentLocalization",
targetCulture,
contentItemUrl = request.Path.Value,
queryStringValue = request.QueryString.Value,
});
return ValueTask.FromResult(FluidValue.Create(url, context.Options));
}
}
View on GitHub (pinned to 4306c0717f)