Skip to content

ARC0023: Generated value declared outside a command Handle method

ARC0023 reports [GeneratedValue] where the declaration is invalid regardless of which commands exist in this or another assembly:

  • The method is not named Handle, including Provide and other method names.
  • The method is static, including a static Handle.
  • The method belongs to a [ReadModel] type, regardless of its name.
  • The method belongs to a controller: a type deriving from Microsoft.AspNetCore.Mvc.ControllerBase, or marked [ApiController] or [Controller]. An action named Handle is still reported.

Inherited read-model and controller declarations are recognized. Default severity: Error.

An instance Handle() that no command uses is not reported. Its attribute is inert: the runtime never reads it. This applies to public base types, sealed non-command types, and inaccessible types alike. The analyzer does not try to predict whether another assembly will define a command subclass.

Only a model-bound command’s effective Handle() participates in generation. When a command uses an inherited handler, ARC0022, ARC0024, and ARC0025 still check that command’s generated parameters.

The examples use this identifier, the same declaration as in generated values:

using System;
using Cratis.Arc.Commands.ModelBound;
using Cratis.Concepts;
public record CartId(Guid Value) : ConceptAs<Guid>(Value), IGeneratable<CartId>
{
public static CartId New() => new(GenerateValue.Uuid());
}

Compile each alternative below together with it, one at a time; the first intentionally produces ARC0023.

[Command]
public record AllocateCartId
{
public CartId Provide([GeneratedValue] CartId cartId) => cartId;
public CartId Handle(CartId cartId) => cartId;
}

Move generation to the handler parameter:

[Command]
public record AllocateCartId
{
public CartId Handle([GeneratedValue] CartId cartId) => cartId;
}

For an ordinary service or read model dependency, remove [GeneratedValue] instead. Arc resolves those dependencies through the normal Provide and dependency injection path.