LuckyPennySoftware/AutoMapper · error · InvalidOperationException

Context.Items are only available when using a Map overload t

Error message

Context.Items are only available when using a Map overload that takes Action<IMappingOperationOptions>! Consider using Context.TryGetItems instead.

What it means

ResolutionContext.Items is only backed by storage when the top-level Map call passed an Action<IMappingOperationOptions> (where items are set). In a default/empty context (e.g. a nested call or a resolver invoked from a Map overload without options), accessing Items calls CheckDefault which throws InvalidOperationException and suggests TryGetItems. The library deliberately refuses to silently hand back an unavailable dictionary.

Source

Thrown at src/AutoMapper/ResolutionContext.cs:110

    internal static void CheckContext(ref ResolutionContext resolutionContext)
    {
        if (resolutionContext.IsDefault)
        {
            resolutionContext = new(resolutionContext._mapper);
        }
    }
    internal TDestination MapInternal<TSource, TDestination>(TSource source, TDestination destination, MemberMap memberMap) =>
        _mapper.Map(source, destination, this, memberMap: memberMap);
    internal object Map(object source, object destination, Type sourceType, Type destinationType, MemberMap memberMap) =>
        _mapper.Map(source, destination, this, sourceType, destinationType, memberMap);
    private void CheckDefault()
    {
        if (IsDefault)
        {
            ThrowInvalidMap();
        }
    }
    private static void ThrowInvalidMap() => throw new InvalidOperationException("Context.Items are only available when using a Map overload that takes Action<IMappingOperationOptions>! Consider using Context.TryGetItems instead.");
}
public readonly record struct ContextCacheKey(object Source, Type DestinationType)
{
    public override int GetHashCode() => HashCode.Combine(DestinationType, RuntimeHelpers.GetHashCode(Source));
    public bool Equals(ContextCacheKey other) => DestinationType == other.DestinationType && Source == other.Source;
}

View on GitHub (pinned to dfa6dd587c)

Solutions

  1. Replace context.Items with context.TryGetItems(out var items) and handle the null/items-missing case gracefully.
  2. At call sites that need items, use mapper.Map<S,D>(src, opts => opts.Items["key"] = value) so a non-default context is in effect.
  3. Make item consumption optional and fall back to a sensible default when items are absent.
  4. Audit every resolver/converter to ensure none assume Items is always populated.

Example fix

// before
public int Resolve(Source s, Dest d, int dest, ResolutionContext ctx) => (int)ctx.Items["factor"];
var dto = mapper.Map<Dest>(src); // throws: Items unavailable

// after
public int Resolve(Source s, Dest d, int dest, ResolutionContext ctx) =>
    ctx.TryGetItems(out var items) && items.TryGetValue("factor", out var f) ? (int)f : 1;
var dto = mapper.Map<Dest>(src);
Defensive patterns

Strategy: validation

Validate before calling

// Always probe with TryGetItems before touching Items:
if (context.TryGetItems(out var items) && items.TryGetValue("factor", out var f))
{
    factor = (int)f;
}
else
{
    factor = 1; // safe default when no options callback was supplied
}

Prevention

When it happens

Trigger: Reading context.Items["key"] from a value resolver, type converter, BeforeMap/AfterMap, or custom mapper when the outer Map used the simple overload mapper.Map<S,D>(src) with no options callback, leaving IsDefault true.

Common situations: A resolver reads Items but some call sites use the parameterless Map overload; a refactor dropped the options callback; unit-testing a resolver in isolation; items that were assumed to always be present.


AI-assisted analysis of LuckyPennySoftware/AutoMapper@dfa6dd587c (2026-08-13). Data as JSON: /api/errors/333ec571cb90982e. Report an issue: GitHub.