Repository navigation
Regression in autofac 9.3.3 resolution #1503
Description
Describe the Bug
Upgrading to Autofac 9.3.3 causes System.InvalidOperationException: Component pipeline has already been built, and cannot be modified. when resolving an open generic component registered with multiple services (e.g. .As(typeof(IFirstService<>)).As(typeof(ISecondService<>))) if Autofac. Extensions.DependencyInjection (or any listener that attaches to PipelineBuilding via ComponentRegistryBuilder.Registered) is used.
I believe the regressions source is in commit 6d74fde (PR #1499 / issue #1465). The pipeline is pre-built
if (additionalInfo.IsSourceQueued(source))
{
// Recording the implementation publishes it to whichever thread drains this source next,
// and that thread resolves through it, so its pipeline has to be built first. Building
// is idempotent, so the call AddRegistration makes later does nothing.
if (_ephemeralServiceInfo is null)
{
provided.BuildResolvePipeline(this);
}
DeferSourceImplementation(additionalInfo, source, provided);
}and the assumption was that it is idempotent, however that doesn't seem to be the case since somewhere along the line ComponentRegistration.PipelineBuilding throws when IsPipelineBuilt == true.
Steps to Reproduce
The following unit test shows the regression
[Fact]
public void MultiServiceOpenGenericCanAttachToPipelineBuildingViaRegistryEvent()
{
var builder = new ContainerBuilder();
builder
.RegisterGeneric(typeof(BothServices<>))
.As(typeof(IFirstService<>))
.As(typeof(ISecondService<>));
builder.ComponentRegistryBuilder.Registered += (sender, e) =>
{
e.ComponentRegistration.PipelineBuilding += (sender, pipeline) => { };
};
using var container = builder.Build();
Assert.NotNull(container.Resolve<IFirstService<int>>());
Assert.NotNull(container.Resolve<ISecondService<int>>());
}Expected Behavior
Should resolve the services without throwing.
Exception with Stack Trace
System.InvalidOperationException: Component pipeline has already been built, and cannot be modified.
at Autofac.Core.Registration.ComponentRegistration.add_PipelineBuilding(EventHandler`1 value)
at Autofac.Extensions.DependencyInjection.AutofacRegistration.AddFromKeyedServiceParameterMiddleware(Object sender, ComponentRegisteredEventArgs
e)
at Autofac.Core.Registration.ComponentRegistryBuilder.OnRegistered(Object sender, IComponentRegistration e)
at Autofac.Core.Registration.DefaultRegisteredServicesTracker.AddRegistration(IComponentRegistration registration, Boolean preserveDefaults,
IRegistrationSource originatingSource)
at Autofac.Core.Registration.DefaultRegisteredServicesTracker.PopulateServiceInfo(Service service, ServiceRegistrationInfo info, Boolean
isScopeIsolatedService)
Dependency Versions
Autofac: 9.3.3 (works on 9.3.2)
Activity
nietras commentedon Sep 18, 2026
We have observed this too.
[-]Regression in autofac 9.3.3 reso[/-][+]Regression in autofac 9.3.3 resolution[/+]tillig commentedon Sep 18, 2026
Thanks for the report, and for pinning it to the exact line — your diagnosis is correct.
AddRegistrationraisesRegisteredbefore it builds the pipeline, precisely so listeners can attach toPipelineBuilding. Holding the implementation for the second service built it before that point, so by the timeRegisteredfired the pipeline already existed and the add accessor threw.BuildResolvePipelineis idempotent, as the comment said, but that was the wrong property to rely on — what matters is the ordering around it, which I broke.Fix is up in #1504, with your repro as a regression test. It removes the early build rather than reordering it, because the window that build was guarding predates the change: 9.3.2 throws the same
Component pipeline has not yet been builtunder concurrent first resolution, so removing it restores 9.3.2's ordering rather than trading one bug for another. That residual concurrent race is tracked separately in #1500.Sorry for the breakage.
Do not build a held registration's pipeline early (#1504)
hjalle commentedon Sep 18, 2026
Thanks for the quick fix @tillig
tillig commentedon Sep 18, 2026
Released just now in 9.3.4.
hjalle commentedon Sep 18, 2026
Works for me now, thanks!