---
title: 'CHR0015: Projection must not have side effects'
---

## Rule Description

A class implementing `IProjectionFor<T>` must not inject `ICommandPipeline` or `IEventLog` via its constructor. Projections are pure state builders that derive read models from events and must not produce side effects.

## Severity

Error

## Example

### Violation

```csharp
using Cratis.Chronicle.EventSequences;
using Cratis.Chronicle.Projections;

public class UserReadModel { }

public class UserProjection : IProjectionFor<UserReadModel>
{
    readonly IEventLog _eventLog;

    public UserProjection(IEventLog eventLog)
    {
        _eventLog = eventLog;
    }

    public void Define(IProjectionBuilderFor<UserReadModel> builder) =>
        builder.From<UserRegistered>(_ => _);
}
```

### Fix

```csharp
using Cratis.Chronicle.Projections;

public class UserReadModel { }

public class UserProjection : IProjectionFor<UserReadModel>
{
    public void Define(IProjectionBuilderFor<UserReadModel> builder) =>
        builder.From<UserRegistered>(_ => _);
}
```

## Why This Rule Exists

Projections declare how to build a read model from a stream of events. They are evaluated at replay time and must be purely declarative. Injecting `IEventLog` or `ICommandPipeline` implies intent to perform side effects during projection evaluation, which breaks idempotency and replay safety.

## Related Rules

- [CHR0016](/chronicle/code-analysis/chr0016/): Projection Define() must not contain imperative code
- [CHR0017](/chronicle/code-analysis/chr0017/): Constraint must not have side effects
