---
title: 'CHR0028: Redundant .AutoMap() call'
---

import { Tabs, TabItem } from '@astrojs/starlight/components';

## Rule Description

AutoMap is enabled by default on projection builders, so calling `.AutoMap()` explicitly has no effect. Remove the redundant call. Use `.NoAutoMap()` when you need to disable the default behavior.

## Severity

Warning

## Example

<Tabs syncKey="chronicle-client">
<TabItem label="C#">

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

public record Chr0028Product(string Name);

[EventType]
public record Chr0028ProductRegistered(string Name);

public class Chr0028ProductProjection : IProjectionFor<Chr0028Product>
{
    public void Define(IProjectionBuilderFor<Chr0028Product> builder) =>
        builder
            .From<Chr0028ProductRegistered>()
            // Warning CHR0028: '.AutoMap()' is redundant — AutoMap is enabled by default. Remove the call.
            .AutoMap();
}
```

</TabItem>
</Tabs>

## Why This Rule Exists

A fluent `IProjectionFor<T>` projection maps each referenced event's properties onto identically named read model properties on its own — AutoMap is on from the moment the builder starts. Calling `.AutoMap()` therefore only restates the default: it changes nothing and adds noise that suggests mapping is being configured when it is not.

The method exists for one narrow purpose — re-enabling AutoMap inside a scope where you first turned it off with `.NoAutoMap()`. Outside that scope the call is redundant. When you actually want to take control of mapping, reach for `.NoAutoMap()` and set the properties yourself; a bare `.AutoMap()` never expresses intent.

## Related Rules

- **CHR0029** — a `.Set(...).To(...)` mapping whose source and target names match, which AutoMap already handles.
- [Model-bound projections](/chronicle/projections/model-bound/) — the full reference.
