Skip to content

Diagnostics

Compiler diagnostics emitted by DesignPatterns source generators and analyzers. IDs are defined in DesignPatterns.Diagnostics.DiagnosticIds.

Help links in the IDE point to this page (#dp### anchors).

Singleton (DP001–DP002)

IDSeverityWhen
DP001Error[GenerateSingleton] target is not partial
DP002ErrorInvalid singleton target (must be sealed class with parameterless ctor)

Strategy (DP003–DP007)

IDSeverityWhen
DP003ErrorDuplicate strategy key
DP004ErrorImplementation does not match strategy contract
DP005(reserved / handler overlap — see DP005 under Chain)
DP006InfoImplementation type not registered with [RegisterStrategy]
DP007ErrorStrategy implementation missing parameterless constructor

Chain of Responsibility (DP005, DP008–DP009, DP024)

IDSeverityWhen
DP005ErrorDuplicate [HandlerOrder] value
DP008ErrorHandler does not implement the pipeline contract
DP009ErrorHandler missing parameterless constructor
DP024InfoHandler type not registered with [HandlerOrder]

Composite (DP010–DP015)

IDSeverityWhen
DP010ErrorDuplicate composite part key
DP011ErrorUnknown parent key
DP012ErrorCycle in composite tree
DP013ErrorPart does not match node contract
DP014ErrorPart missing parameterless constructor
DP015ErrorRegistry holder missing [CompositeBuildable]

Decorator (DP016–DP019)

IDSeverityWhen
DP016ErrorDuplicate decorator order
DP017ErrorDecorator does not match contract
DP018ErrorType does not implement IDecorator<T>
DP019ErrorDecorator missing parameterless constructor

Factory Registry (DP020–DP023)

IDSeverityWhen
DP020ErrorDuplicate factory key
DP021ErrorFactory does not match product contract
DP022ErrorFactory missing parameterless constructor
DP023InfoProduct type not registered with [RegisterFactory]

Registry key (DP025)

IDSeverityWhen
DP025InfoString literal key passed to a generated Strategy or Factory registry lookup is not among registered keys

Where it applies: Get / TryGet / Create / TryCreate on IStrategyRegistry<,> / IFactoryRegistry<,> when the key argument is a string literal (not a {Contract}Keys constant).

Message: includes the contract type and the list of registered keys.

Fix: prefer {Contract}Keys.* constants. The CorrectRegistryKey CodeFix suggests the closest registered key when the typo is near a known key.

See also Registry key conventions.

Plugin assemblies (DP033)

IDSeverityWhen
DP033ErrorThe same strategy key for the same contract is registered in more than one referenced provider assembly

Where it applies: host (or any) compilations that reference multiple plugin provider assemblies contributing [RegisterStrategy] / [RegisterStrategy<TContract>] for the same contract with an identical key string.

Message: includes the key, contract type, and conflicting assembly names.

Fix: use distinct keys per provider assembly, or reference only one provider per contract dimension. Duplicate keys within a single assembly remain DP003 (generator).

See Plugin assemblies sample, the main repo PluginAssemblies.md, and Configuration.

State transition table (DP026–DP031)

IDSeverityWhen
DP026ErrorDuplicate (from state, trigger) edge
DP027Error[Transition] state value is not a declared enum member
DP028Error[Transition] trigger value is not a declared enum member
DP029Error[StateMachine] Initial is not a declared state enum member
DP030ErrorHolder class is not static partial
DP031InfoState enum member never appears as a [Transition] source (terminal/reserved hint)

See State transition table.

State guard (DP032, DP034–DP035)

IDSeverityWhen
DP032Error[Transition(Guard = nameof(Method))] guard method not found on holder class
DP034ErrorGuard method is not static (defensive — C# compiler rejects instance methods on static classes first)
DP035ErrorGuard method has wrong signature (must be static bool Method(TState, TTrigger))

State literal edge (DP036)

IDSeverityWhen
DP036InfoTryTransition called with literal (state, trigger) arguments that do not match any declared [Transition] edge

State entry/exit actions (DP037–DP039)

IDSeverityWhen
DP037Error[Transition(OnEnter/OnExit = nameof(Method))] action method not found on holder class
DP038ErrorAction method is not static (unreachable in practice — CS0708 fires first; retained for completeness)
DP039ErrorAction method has wrong signature (must be static void Method(TState, TState, TTrigger) or static ValueTask Method(TState, TState, TTrigger, CancellationToken))

Composite DI + Visitor (DP040–DP041)

IDSeverityWhen
DP040ErrorBuildRoot(IServiceProvider) called but a composite node is not registered in the container
DP041InfoGenerated I{Contract}NodeVisitor does not cover all node types (reserved — the C# compiler enforces full coverage via CS0535 when implementing the generated interface)

Decorator DI + async (DP042–DP043)

IDSeverityWhen
DP042ErrorAsync decorator method signature is incorrect (DecorateAsync must return ValueTask<TService>)
DP043ErrorAsync decorator cannot be resolved from DI when using Build(IServiceProvider, core)

EventAggregator (DP044–DP046)

IDSeverityWhen
DP044InfoType implements IEventHandler<T> but is not marked with [RegisterEventHandler]
DP045ErrorDuplicate [RegisterEventHandler] on the same handler for the same event type
DP046ErrorType marked with [RegisterEventHandler<T>] but does not implement IEventHandler<T>

Strategy guard (DP047–DP049)

IDSeverityWhen
DP047Error[RegisterStrategy(Guard = nameof(Method))] guard method not found on strategy class
DP048ErrorGuard method is not static
DP049ErrorGuard method has wrong signature (must be static bool Method(TKey))

Handler guard (DP050–DP052)

IDSeverityWhen
DP050Error[HandlerOrder(Guard = nameof(Method))] guard method not found on handler class
DP051ErrorGuard method is not static
DP052ErrorGuard method has wrong signature (must be static bool Method(TContext))

Factory async + pooling (DP053–DP055)

IDSeverityWhen
DP053Error[RegisterFactory(IsAsync = true)] but factory does not implement IAsyncFactory<T>
DP054ErrorPoolSize is negative (must be ≥ 0; 0 disables pooling)
DP055WarningPoolSize > 1024 (may cause excessive memory usage)

State hierarchy (DP056–DP059)

IDSeverityWhen
DP056ErrorA state hierarchy contains a cycle
DP057Error[StateParent] references a state that is not a member of the state enum
DP058Error[StateParent] declares a state as its own parent
DP059InfoA declared parent state has no children and no outgoing transitions

DI lifetime (DP060–DP062)

IDSeverityWhen
DP060WarningA generated registry lifetime exceeds the implementation lifetime and may capture a shorter-lived service
DP061InfoAn implementation lifetime exceeds the registry lifetime and may cause unnecessary instances
DP062WarningA Singleton service depends on a Scoped or Transient service

Composite tree schema (DP063–DP065)

IDSeverityWhen
DP063WarningA Composite tree exceeds the MaxDepth declared by [CompositeSchema]
DP064ErrorA Composite child type is not listed in the parent’s AllowedChildTypes
DP065WarningA Composite contract exceeds the MaxNodes declared by [CompositeSchema]

Singleton lifecycle (DP066–DP071)

IDSeverityWhen
DP066WarningA Singleton factory delegate resolves a Scoped or Transient service and captures it
DP067ErrorA GenerateSingleton asynchronous initializer is missing, non-static, or has an invalid Task/ValueTask signature
DP068WarningA generated singleton is also registered as a DI Singleton, creating two lifecycle owners
DP069InfoA non-thread-safe generated singleton contains mutable instance state
DP070InfoMutable static singleton state was detected; prefer an immutable Lazy-backed singleton or DI
DP071WarningMutable static singleton state is also registered as a DI Singleton

Code fixes

DesignPatterns.CodeFixes ships inside the Skymly.DesignPatterns meta package (analyzers/dotnet/cs). Selected diagnostics offer one-click fixes in the IDE (requires C# Workspaces):

DiagnosticCode fix (summary)
DP006Add [RegisterStrategy("key", typeof(TContract))]
DP023Add [RegisterFactory("key", typeof(TContract))]
DP024Add [HandlerOrder(order, typeof(TContext))]
DP025Replace literal with nearest registered key
DP001Add partial modifier
DP015Add [CompositeBuildable]
DP004 / DP013 / DP017 / DP021Add contract implementation
DP007 / DP009 / DP014 / DP019 / DP022Add parameterless constructor

Generator errors (DP001–DP005, DP007–DP022) are fixed by correcting attributes or types; no CodeFix is provided for duplicate-key errors.

Category prefix: DesignPatterns.

Released under the MIT License.