---
title: 'ARC0006: Command-scoped read model can be missing'
description: Choose nullable or required read model dependencies deliberately, and distinguish missing state from missing registration.
---


<a id="severity"></a>

## Rule

A non-nullable read model parameter makes state a required dependency. Make the parameter nullable when the command handles absence as a normal outcome; retain a required parameter when absence should reject the command. **Default severity: Warning.**

The analyzer checks:

- constructors of `CommandValidator<TCommand>` types,
- public instance `Provide()` methods on `[Command]` types,
- public instance `Handle()` methods on `[Command]` types.

It recognizes types marked `[ReadModel]` and, when Chronicle is referenced, types used by `IProjectionFor<TReadModel>` implementations in the current compilation. This compile-time recognition does not register a runtime provider or prove that an instance exists.

<a id="example"></a>
<a id="reported-code"></a>

## Diagnostic example

This standalone Arc declaration deliberately produces ARC0006. Compile it in a project referencing `Cratis.Arc.Core` with nullable reference types enabled. It is **not a runnable lookup**: a real application must configure the read model provider and its key resolution.

```csharp
#nullable enable
using Cratis.Arc.Commands;
using Cratis.Arc.Commands.ModelBound;
using Cratis.Arc.Queries.ModelBound;
using FluentValidation;

[Command]
public record SubmitOrder(string OrderId)
{
    public string Handle() => OrderId;
}

[ReadModel]
public record OrderState(bool Ready);

public class SubmitOrderValidator : CommandValidator<SubmitOrder>
{
    public SubmitOrderValidator(OrderState order)
    {
        RuleFor(_ => order.Ready)
            .Equal(true)
            .WithMessage("Order must be ready for submission");
    }
}
```

The command has a public handler and the read model is a record, so neither ARC0004 nor ARC0008 obscures the intended warning. The string identifier does not, by itself, configure command-scoped lookup.

<a id="option-1-handle-missing-state"></a>

## Handle missing state explicitly

Replace the validator above with this nullable version when you want the validator itself to report absence:

```csharp
public class SubmitOrderValidator : CommandValidator<SubmitOrder>
{
    public SubmitOrderValidator(OrderState? order)
    {
        RuleFor(_ => order)
            .NotNull()
            .WithMessage("Order does not exist");

        When(_ => order is not null, () =>
        {
            RuleFor(_ => order!.Ready)
                .Equal(true)
                .WithMessage("Order must be ready for submission");
        });
    }
}
```

This is a replacement fragment using the first block's types and imports. The guard prevents dereferencing an absent instance. For creation commands, absence might instead be the desired condition; choose rules for your use case, not merely to silence the warning.

<a id="option-2-require-existing-state"></a>

## Require existing state

Retain the non-nullable parameter when missing state should fail before the validator is constructed. Review or narrowly suppress the warning to record that deliberate choice. Nullable annotations do not fix provider registration or guarantee lookup success.

For a registered command-scoped read model provider:

| Resolution outcome | Current behavior |
| --- | --- |
| Usable key, instance absent, nullable parameter | Receives `null`; application logic decides what absence means |
| Usable key, instance absent, required parameter | `ReadModelDoesNotExistForCommand`, a validation failure mapped to HTTP 400 |
| Provider cannot resolve a usable key | `UnableToResolveReadModelFromCommandContext`, a validation failure mapped to HTTP 400, even for a nullable parameter |
| Required dependency is not registered | `CannotResolveCommandDependency` or `CannotResolveValidatorDependency`, an exception outcome rather than a normal missing-state rejection |

An unregistered nullable dependency can receive `null` without any lookup. Check registration before treating that as evidence that no state exists. The missing-state/key failures carry `ValidationResultReason.DependencyUnavailable`; [testing assertions](/arc/backend/csharp/testing/command-scenario/#dependency-unavailable-is-not-a-business-rule-rejection) distinguish them from rules that actually ran.

<a id="why-this-rule-exists"></a>

## Optional Chronicle behavior

With the Chronicle integration, an event-source identifier or `[Key]` selects a projected instance but does not prove it exists. It may never have been created, may have been removed, or may be unavailable during a rebuild. A Chronicle command without a declared identity gets a generated key; that is different from an unusable resolved key.

Arc alone does not require projected state. For Chronicle-backed invariants that must hold under concurrency, decide whether projected state is sufficient or whether you need source-of-truth state instead.

## Related documentation

- [Use current state in a command](/arc/scenarios/use-current-state-in-a-command/)
- [Read models in Chronicle commands](/arc/backend/csharp/chronicle/read-models/injecting-into-commands/)
- [When Chronicle read model resolution fails](/arc/backend/csharp/chronicle/read-models/failures/)
- [Command validation](/arc/backend/csharp/commands/validation/)
- [Provide data to a command handler](/arc/scenarios/provide-data-to-a-command/)
