Skip to content

Diagnostics

The generator reports what it can work out at build time as DM#### codes, so a registration mistake shows up in the IDE rather than as a resolution failure at startup. This page says what each one means and what to do about it.

These are reported by a source generator rather than by an analyzer, which decides how they are tuned. Roslyn applies .editorconfig severity mapping to analyzer diagnostics, and a generator's reach the compilation with the severity already fixed — so dotnet_diagnostic.DM0005.severity = none has no effect. Use the compilation-level properties instead, which are applied later and do work:

xml
<PropertyGroup>
  <NoWarn>$(NoWarn);DM0005</NoWarn>
  <WarningsAsErrors>$(WarningsAsErrors);DM0013</WarningsAsErrors>
</PropertyGroup>

#pragma warning disable DM0005 works too, for silencing one site rather than a project.

DM0010 and DM0011 are informational and exist to make registration visible at the class, which means they appear in the IDE and never in dotnet build at any verbosity. The rest are worth reading.

CodeSeverityMeaning
DM0001ErrorThe generator failed
DM0002WarningA service type cannot be constructed
DM0003ErrorA module is not partial
DM0004ErrorTwo conventions register a type as the same service type
DM0005WarningA convention matched nothing
DM0006WarningA convention matched a type with no accessible constructor
DM0007ErrorTwo decorators of one service share an order
DM0008WarningA service marked for interception cannot be wrapped
DM0009ErrorA convention declaration could not be read
DM0010InfoA service is registered by convention
DM0011InfoA service is registered only when a condition holds
DM0012WarningAn environment condition names nothing to test
DM0013WarningA service registered as an open generic cannot be decorated
DM0014WarningA generic type cannot be cross-wired
DM0015WarningAn interceptor does not apply to every member
DM0016WarningAn assembly-level module attribute's namespace is not imported

DM0001

The generator failed; registrations may be missing.

Please open an issue with the generator log — see Troubleshooting.

DM0002

A service type cannot be constructed and was not registered.

The implementation is abstract or a static class, so the container could not construct it.

DM0003

A module marked with [DependencyModule] is not partial.

The generator completes the module's partial declaration. Without partial there is nothing to complete.

DM0004

Two conventions in one module register a type as the same service type.

The lifetime would be ambiguous.

csharp
conventions.RegisterAll<IRepository>().AsScoped();
conventions.RegisterAll<IRepository>().AsSingleton();   // DM0004

Equal lifetimes are an error too — the declaration is redundant.

A type filling two different roles is not ambiguous and registers as both. Conventions in different modules never collide; each registers into its own realm.

DM0005

A convention matched no types.

Almost always a renamed interface or a typo in a filter.

DM0006

A convention matched a type with no accessible constructor.

The container could not construct it.

DM0007

Two decorators of one service share an order.

Their nesting would be ambiguous. See Decorators.

DM0008

A service marked for interception cannot be wrapped.

The member uses ref, in, out or a ref struct parameter, returns by reference, has an init-only setter, or is static.

One such member costs the whole interface: no wrapper is generated, so every other member goes uninterceped too. The message names the first offender it found. See Interception.

DM0009

A convention declaration could not be read.

The Conventions body is read at compile time, so only the documented calls can appear in it — a loop, a conditional, a local or a call to your own helper cannot.

It also covers a convention with no lifetime, a RegisterAll() with no shape or no filter, and a chain that could not be resolved.

DM0010

A service is registered by convention.

Informational, reported at the class, naming the service type it was registered as and the interface the match came through when it was not direct.

A match from a referenced assembly has no class to point at, so it reports at the RegisterAll line instead.

DM0011

A service is registered only when an environment condition holds.

Informational, reported at the class. See Environments.

DM0012

An environment condition names nothing to test.

[IfEnvironment()] and [IfEnvironmentValue("")] both compile. Written plain they mean the service never registers; written as the IfNot form they mean the attribute does nothing at all.

DM0013

A service registered as an open generic cannot be decorated.

Decoration replaces a registration with a factory, and the container does not allow one for an open generic service type — Open generic service type 'IRepository1[T]' requires registering an open generic implementation type`.

csharp
[SingletonService]
public class Repository<T> : IRepository<T> { }   // registers IRepository<> itself

[Decorator]
public class CachingRepository<T>(IRepository<T> inner) : IRepository<T> { }   // DM0013

Reported whichever way the decorator was declared — on the class, or on the module with [Decorate] — and whether or not the decorator is itself generic.

Register closed constructions instead. A convention over the open generic registers one per implementation, and an open generic decorator is expanded across them. See Decorators.

DM0014

A generic type cannot be cross-wired.

[CrossWireService] shares one instance across the implementation and every interface it declares, which is emitted as a factory per interface — and an open generic registration cannot carry one.

csharp
[CrossWireService]
public class Ledger<T> : ILedger<T>, IAudit<T> { }   // DM0014

Registering each interface to the same open generic implementation type would compile, and is a different contract: the container builds one instance per service type, which is the opposite of what the attribute promises.

Use [SingletonService], [ScopedService] or [TransientService] instead, applying one per interface if the type needs to answer to more than one.

DM0015

An interceptor does not apply to every member it was applied to.

Three interfaces cover the member shapes, and the generator picks per member:

InterfaceMembers
IInterceptorreturning a value directly, or void
IAsyncInterceptorreturning Task, Task<T>, ValueTask, ValueTask<T>
IAsyncEnumerableInterceptorreturning IAsyncEnumerable<T>

An interceptor that implements none of the one a member needs is left out of that member's chain, and those calls run without it:

csharp
public class AuditInterceptor : IInterceptor { … }      // sync only

[SingletonService]
[Intercept(typeof(AuditInterceptor))]
public class Orders : IOrders {
    public int Count(string customer) { … }             // audited
    public Task<int> CountAsync(string customer) { … }  // DM0015 — not audited
}

This matters more than it first reads. An interceptor that rewrites arguments stops rewriting them; one that authorises or audits stops doing that, on exactly the members most likely to be the interesting ones. In the sharpest case — an IInterceptor applied to a service whose members are all async — it never runs at all.

Implement the missing interface on the interceptor, or apply it to a service with no such member.

Reported once per interceptor and member shape, so a wide interface produces one line rather than one per member. See Interception.

DM0016

An assembly-level module attribute's namespace is not imported.

A module generates its attribute in the module's own namespace, and an assembly-level attribute has no namespace context to inherit — a using written inside a namespace declaration cannot apply to it, because assembly attributes precede every namespace in the file.

csharp
// Bootstrap.cs
using DependencyModules.NSubstitute;

[assembly: ApplicationModule]     // DM0016 — nothing brings MyApp.Composition into scope
[assembly: NSubstituteSupport]

Left alone this is CS0246: The type or namespace name 'ApplicationModuleAttribute' could not be found — a type you never wrote, generated into a namespace the error does not name. Every part of that message points away from the fix, which is one line:

csharp
using MyApp.Composition;          // or write it as [assembly: MyApp.Composition.ApplicationModule]

Unlike the other diagnostics here this one is read from syntax rather than from the compiler's view of your code, and it has to be: the attribute is written by the generator that is running, so it does not exist in the compilation being examined and nothing about it can be resolved. The check is therefore "is there a module by this name, and could this file see it" — which is why it stays quiet for an attribute matching no module in the compilation, a module in the global namespace, a usage already written qualified, and a namespace supplied by a global using in any file.

See Testing and Modules.

Released under the MIT License.