Diagnostic Codes

Read time 12 minutes Package: Nalix.Analyzers
On this page

This page lists all 75 active diagnostic descriptors emitted by Nalix.Analyzers (67 rules in analyzers/Nalix.Analyzers/Diagnostics/DiagnosticDescriptors.cs) and Nalix.Analyzers.Generators (8 rules in analyzers/Nalix.Analyzers.Generators/Internal/GeneratorDiagnosticDescriptors.cs).

1. Controller Dispatch and Packet Registration (NALIX001–NALIX018, NALIX047–NALIX058)

IDTitleSeverityCategoryCode FixDescription
NALIX001Packet controller contains duplicate PacketOpcodeWarningUsageNoController dispatch relies on unique opcodes per controller.
NALIX002Packet controller handler should declare PacketOpcodeWarningUsageYesController methods matching Nalix handler patterns should declare [PacketOpcode(...)].
NALIX003Packet controller handler has unsupported signatureWarningUsageNoParameter 0 must be IPacketContext<TPacket>. Any additional parameters (1..N) must be reference types annotated with [FromScope] (see NALIX067).
NALIX004PacketContext<T> does not match dispatch packet typeWarningUsageNoPacketContext<T> should use a packet type assignable to the dispatcher’s TPacket.
NALIX005Registered controller handler packet type does not match dispatcher typeWarningUsageNoControllers registered on PacketDispatchOptions<TPacket> must handle compatible packet types.
NALIX008Registered handler controller is missing PacketHandlerWarningUsageYesTypes registered through WithHandler or MapHandlers must declare [PacketHandler].
NALIX009Registered packet type is missing static DeserializeWarningUsageYesPacket registry binding expects IPacketDeserializer<T> / static Deserialize(ReadOnlySpan<byte>) support.
NALIX010PacketBase<TSelf> should use the containing packet typeWarningUsageYesPacketBase<TSelf> must pass the containing packet class as TSelf (CRTP).
NALIX011IPacketDeserializer<T> should use the containing packet typeWarningUsageYesPacket deserializer contracts must target the containing packet type.
NALIX012PacketBase packet should expose static DeserializeWarningUsageYesPacketBase<TSelf> packet types should expose an accessible public static new TSelf Deserialize(ReadOnlySpan<byte>).
NALIX017Packet Deserialize signature is invalidWarningUsageNoDeserialize must be public static new {Packet} Deserialize(ReadOnlySpan<byte>).
NALIX018Registered packet type must be concreteWarningUsageNoPacket registry entries must be concrete, non-abstract, non-generic packet types.
NALIX047Dispatch loop count is out of supported rangeWarningUsageYesWithDispatchLoopCount expects a value in 1..64 (or null for automatic scaling).
NALIX048Packet controller handler return type is unsupportedWarningUsageNoSupported return types are void, Task, ValueTask, TResult, Task<TResult>, ValueTask<TResult>, and IAsyncEnumerable<TElement>.
NALIX050PacketOpcode is declared on a non-controller typeInfoUsageNo[PacketOpcode] handlers must be declared inside [PacketHandler] controller classes.
NALIX052Packet Deserialize overload should include ReadOnlySpan<byte>WarningUsageYesPacket discovery requires a Deserialize(ReadOnlySpan<byte>) overload.
NALIX054PacketHandler name is duplicatedInfoUsageNoDuplicate [PacketHandler("...")] names reduce routing and diagnostic clarity.
NALIX055Redundant cast on PacketContext<T>.PacketInfoUsageYescontext.Packet is already strongly typed as T.
NALIX056Middleware registration uses nullWarningUsageYesMiddleware registration methods require non-null middleware instances.
NALIX058Packet handler method should not be genericWarningUsageYesGeneric packet handler methods cannot be bound to a concrete wire opcode.

2. Middleware and Routing Metadata (NALIX006, NALIX025–NALIX038)

IDTitleSeverityCategoryCode FixDescription
NALIX006Registered middleware type does not match dispatcher packet typeWarningUsageNoIPacketMiddleware<TPacket> must match the dispatcher’s packet type.
NALIX025Packet metadata provider clears OpcodeWarningRoutingNoCustom IPacketMetadataProvider implementations must not set builder.Opcode = null.
NALIX026Packet metadata provider overwrites Opcode without guardInfoRoutingNoMetadata providers should guard assignments with builder.Opcode ??= ... instead of overwriting unconditionally.
NALIX030Packet middleware should declare MiddlewareOrderInfoMiddlewareYesExplicit [MiddlewareOrder(n)] makes middleware execution order deterministic.
NALIX032Inbound middleware ignores AlwaysExecuteInfoMiddlewareYesMiddlewareStage.Inbound ignores AlwaysExecute = true (AlwaysExecute only applies to Outbound and Both).
NALIX033Registered middleware shares MiddlewareOrder with another middleware in the same chainInfoMiddlewareNoDuplicate [MiddlewareOrder] values in one pipeline chain reduce ordering predictability.
NALIX035PacketOpcode is in reserved rangeWarningUsageNoOpcodes 0x0000..0x00FF (0..255) are reserved for Nalix system/protocol frames. Use >= 0x0100 for application packets.
NALIX036PacketOpcode is already used in a different controllerWarningUsageNoEvery handler registered on the same dispatcher must have a globally unique opcode.
NALIX038OpCode in documentation does not match attributeInfoDocumentationNoXML doc comments mentioning an opcode should match the [PacketOpcode] attribute value.

3. Serialization Layout (NALIX013–NALIX022, NALIX034, NALIX046, NALIX051)

IDTitleSeverityCategoryCode FixDescription
NALIX013Explicit serialization member should declare SerializeOrderWarningSerializationYesTypes with [SerializePackable(SerializeLayout.Explicit)] should annotate serialized members with [SerializeOrder(n)] or [SerializeIgnore].
NALIX014SerializeOrder value is duplicatedWarningSerializationYes[SerializeOrder] values must be unique across all serialized members of a type hierarchy.
NALIX015SerializeIgnore conflicts with SerializeOrderWarningSerializationYesA member cannot have both [SerializeIgnore] and [SerializeOrder].
NALIX016SerializeDynamicSize is unnecessary on fixed-size memberInfoSerializationNo[SerializeDynamicSize] is only meaningful on variable-size members (string, arrays, collections).
NALIX021SerializeOrder should not be negativeWarningSerializationNo[SerializeOrder] indices must be >= 0.
NALIX022SerializeHeader(0) is reserved on PacketBase typesWarningSerializationNoOn PacketBase<TSelf> subclasses, order 0 (PacketHeaderOffset.Header) is occupied by PacketBase.Header. Start user fields at order 0 via [SerializeOrder(0)] or non-zero header offsets.
NALIX034SerializeHeader conflicts with SerializeOrderWarningSerializationNoDo not combine [SerializeHeader] and [SerializeOrder] on the same member.
NALIX046SerializeOrder gap is unusually largeInfoSerializationNo[SerializeOrder] is sequential field ordering metadata, not a raw byte offset. Gaps > 16 trigger this hint.
NALIX051IFixedSizeSerializable type contains dynamic serialization memberWarningSerializationNoTypes implementing IFixedSizeSerializable cannot contain variable-length strings, arrays, or collections.

4. Lifecycle, Configuration, SDK, and Hosting (NALIX020, NALIX023–NALIX028, NALIX037, NALIX039–NALIX045, NALIX057)

IDTitleSeverityCategoryCode FixDescription
NALIX020Packet ResetForPool should call base.ResetForPoolWarningLifecycleYesCustom ResetForPool() overrides on PacketBase<TSelf> must call base.ResetForPool() so the base header and priority are reset.
NALIX023Configuration property type is not supportedWarningConfigurationYesConfigurationLoader supports primitives, decimal, string, Guid, TimeSpan, DateTime, and enum properties.
NALIX024Configuration property is not bindableInfoConfigurationYesPublic ConfigurationLoader properties without a public setter cannot be bound from .ini files and should declare [ConfiguredIgnore].
NALIX027RequestOptions.RetryCount should not be negativeWarningSDKNoRequestOptions.RetryCount must be >= 0.
NALIX028RequestOptions.TimeoutMs should not be negativeWarningSDKNoRequestOptions.TimeoutMs must be >= 0 (0 disables the per-attempt timeout).
NALIX037Potential allocation in hot pathInfoPerformanceNoWarns on new byte[...], .ToArray(), or LINQ allocations inside packet handlers, middleware, and serializer methods.
NALIX039Potential IBufferLease leakWarningUsageNoEvery rented IBufferLease must be disposed via using, returned, or transferred across all control paths.
NALIX040NetworkApplicationBuilder should configure BufferPoolManagerInfoPerformanceNoSuggests calling .UseBufferPoolManager(...) when building a custom host pipeline.
NALIX041NetworkApplicationBuilder should configure ConnectionHubInfoUsageNoSuggests calling .UseConnectionHub(...) when building a custom host pipeline.
NALIX042NetworkApplicationBuilder handler type is not constructibleWarningUsageNoController types passed to MapHandlers must be concrete, constructible classes.
NALIX043NetworkApplicationBuilder metadata provider type is not constructibleWarningUsageNoMetadata provider types must be concrete, constructible classes.
NALIX044NetworkApplicationBuilder should configure a TCP bindingInfoUsageNoWarns when .Build() is called without any transport listener binding.
NALIX045NetworkApplicationBuilder should configure TCP before UDPInfoUsageNoAuthenticated UDP listeners rely on sessions established over TCP (MapTcp should accompany MapUdp).
NALIX057RequestOptions uses infinite timeout with retriesInfoSDKYesSetting TimeoutMs = 0 with RetryCount > 0 makes retries unreachable because the first attempt waits indefinitely.

5. Source Generator Diagnostics (NALIX059–NALIX068)

Emitted by Nalix.Analyzers.Generators (analyzers/Nalix.Analyzers.Generators/Internal/GeneratorDiagnosticDescriptors.cs):

IDTitleSeverityCategoryGeneratorDescription
NALIX059Missing static Create() methodErrorNalix.Codec.SerializationSerializeFormatterGeneratorReference type marked [GenerateFormatter] must declare a static Create() method returning an instance for pooling/deserialization (inherited automatically by PacketBase<TSelf> subclasses).
NALIX060Packet class must be partialErrorNalix.Codec.SerializationPacketSchemaGeneratorClasses inheriting from PacketBase<TSelf> must be declared partial so PacketSchemaGenerator can emit Length, ResetForPool(), and Size.
NALIX063No accessible constructor foundErrorNalix.Framework.InjectionInstanceGenerator[Injectable] class has no public or internal constructor that the source generator can invoke.
NALIX064Ambiguous constructors in injectable classErrorNalix.Framework.InjectionInstanceGenerator[Injectable] class has multiple public/internal constructors with the same non-config parameter count (args.Length) and non-disjoint parameter types.
NALIX065SingletonBase subclass missing accessible parameterless constructorWarningNalix.Framework.InjectionInstanceGeneratorSingletonBase<T> subclass has no public or internal parameterless constructor (protected alone is not accessible to the generated initializer).
NALIX066Unsupported [RpcService] method return typeErrorNalix.SDK.TransportRpcClientGenerator[RpcService] interface methods must return ValueTask, ValueTask<T>, RpcCall<T>, or RpcStream<T>.
NALIX067Handler method dropped from dispatch tableErrorNalix.Runtime.DispatchingPacketHandlerGeneratorParameter 0 of a [PacketOpcode] handler is IPacketContext<TPacket>; any additional parameter (1..N) must be a reference type annotated with [FromScope].
NALIX068Duplicate packet StaticOpCodeErrorNalix.Codec.DataFramesPacketRegistryGeneratorTwo or more packet classes in the compilation define the same StaticOpCode.

6. Security, Pooling, RPC, Injection, and Lifecycle Diagnostics (NALIX071–NALIX107)

IDTitleSeverityCategoryScopeDescription
NALIX071Use Nalix crypto abstractions instead of System.Security.CryptographyWarningSecurityCore-onlyDirect BCL crypto usage in Nalix Core assemblies bypasses security review (OsCsprng and CryptographicOperations.FixedTimeEquals are allowlisted).
NALIX072Use zero-allocation endpoint formatting in hot pathsInfoPerformanceCore-onlyIPAddress.ToString(), INetworkEndpoint.Address, and SocketEndpoint.Address allocate strings. Prefer TryFormatAddress on hot paths.
NALIX073Unguarded catch(Exception)WarningCorrectnessCore-onlyBare catch or catch (Exception) clauses in Core assemblies must either filter via when (...) or rethrow so fatal runtime exceptions are not swallowed.
NALIX074Avoid eager string formatting in diagnostic loggingInfoPerformanceCore-onlyInterpolated strings, string.Format, or concatenation inside new DiagnosticLog(...) allocate even when diagnostics are disabled. Guard with DiagnosticsEvents.Source.IsEnabled(...).
NALIX075PacketScope<T> must be disposedErrorPoolingAll assembliesPacketScope<T> wraps a pooled packet and must be declared with using (using PacketScope<T> scope = ...) or explicitly disposed.
NALIX076Packet context escapes handler scopeErrorCorrectnessAll assembliesIPacketContext<T> and context.Packet are pooled and returned immediately when the handler finishes. Capturing them in fields, properties, arrays/collections, events, or Task.Run / ThreadPool delegates causes use-after-return corruption.
NALIX078Avoid unbounded reflection in AOT-sensitive Nalix Core codeWarningAOTCore-onlyFlags Assembly.GetTypes(), Expression.Compile(), MakeGenericType(), MethodInfo.Invoke(), and Type.GetType(string) in Core assemblies.
NALIX100RpcService method has invalid return typeErrorUsageAll assembliesMethods in [RpcService] interfaces must return ValueTask, ValueTask<T>, RpcCall<T>, or RpcStream<T> (Task and Task<T> are not supported).
NALIX101RpcService method has invalid parametersErrorUsageAll assembliesParameter 0 of an [RpcService] method must implement IPacket; subsequent parameters may only be RequestOptions, Func<TResponse, bool>?, bool?, or CancellationToken.
NALIX102RpcService interface contains non-method membersErrorUsageAll assemblies[RpcService] interfaces can only declare methods (properties, events, and indexers are forbidden).
NALIX103RpcService interface is missing attributeInfoUsageAll assembliesInterfaces containing [PacketOpcode] methods must be decorated with [RpcService] so RpcClientGenerator discovers them.
NALIX104[Inject] field cannot be readonlyErrorUsageAll assembliesFields annotated with [Inject] are populated inside the generated InitializeDependencies() method and cannot be readonly.
NALIX105Nalix analyzer disabled: required symbol could not be resolvedWarningUsageAll assembliesEmitted at compilation start if a required core Nalix symbol cannot be resolved from referenced assemblies.
NALIX106Packet StaticOpCode is already used by another packetErrorUsageAll assembliesTwo packet types in the compilation declare the same StaticOpCode value.
NALIX107Packet ResetForPool does not reset mutable memberWarningLifecycleAll assembliesA manual ResetForPool() override on a packet class omits resetting a mutable field or property that is not marked [SkipClean].

NALIX076 Examples (PacketContextEscapeAnalyzer)

IPacketContext<TPacket> and context.Packet are rented from ObjectPoolManager and automatically returned when the handler’s ValueTask completes.

Safe Patterns

[PacketOpcode(0x1001)]
public async ValueTask HandleEchoAsync(IPacketContext<EchoPacket> context)
{
    // Copy value-type or immutable fields into local variables if needed later
    string message = context.Packet.Message;
    uint seq = context.Packet.SequenceId;

    // Directly awaiting a helper or Sender method within the handler lifetime is safe
    await context.Sender.ReplyAsync(new EchoPacket
    {
        SequenceId = seq,
        Message = message
    }).ConfigureAwait(false);
}

Unsafe Patterns Caught by NALIX076

private static IPacketContext<EchoPacket>? s_leakedContext;

[PacketOpcode(0x1001)]
public void HandleUnsafe(IPacketContext<EchoPacket> context)
{
    // ERROR NALIX076: Storing context or packet in a field/property
    s_leakedContext = context;

    // ERROR NALIX076: Capturing context or a local packet alias in Task.Run
    EchoPacket alias = context.Packet;
    _ = Task.Run(() => ProcessInBackground(alias));

    // ERROR NALIX076: Capturing context in an event handler
    context.Connection.ConnectionClosed += (_, _) => Log(context.Packet);
}