{"record":{"id":"333ec571cb90982e","repo":"LuckyPennySoftware/AutoMapper","slug":"context-items-are-only-available-when-using-a-map","errorCode":null,"errorMessage":"Context.Items are only available when using a Map overload that takes Action<IMappingOperationOptions>! Consider using Context.TryGetItems instead.","messagePattern":"Context\\.Items are only available when using a Map overload that takes Action<IMappingOperationOptions>! Consider using Context\\.TryGetItems instead\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/AutoMapper/ResolutionContext.cs","lineNumber":110,"sourceCode":"    internal static void CheckContext(ref ResolutionContext resolutionContext)\n    {\n        if (resolutionContext.IsDefault)\n        {\n            resolutionContext = new(resolutionContext._mapper);\n        }\n    }\n    internal TDestination MapInternal<TSource, TDestination>(TSource source, TDestination destination, MemberMap memberMap) =>\n        _mapper.Map(source, destination, this, memberMap: memberMap);\n    internal object Map(object source, object destination, Type sourceType, Type destinationType, MemberMap memberMap) =>\n        _mapper.Map(source, destination, this, sourceType, destinationType, memberMap);\n    private void CheckDefault()\n    {\n        if (IsDefault)\n        {\n            ThrowInvalidMap();\n        }\n    }\n    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.\");\n}\npublic readonly record struct ContextCacheKey(object Source, Type DestinationType)\n{\n    public override int GetHashCode() => HashCode.Combine(DestinationType, RuntimeHelpers.GetHashCode(Source));\n    public bool Equals(ContextCacheKey other) => DestinationType == other.DestinationType && Source == other.Source;\n}","sourceCodeStart":92,"sourceCodeEnd":116,"githubUrl":"https://github.com/LuckyPennySoftware/AutoMapper/blob/dfa6dd587c5854b4beee5934beb39ba6e9569b84/src/AutoMapper/ResolutionContext.cs#L92-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Replace context.Items with context.TryGetItems(out var items) and handle the null/items-missing case gracefully.","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.","Make item consumption optional and fall back to a sensible default when items are absent.","Audit every resolver/converter to ensure none assume Items is always populated."],"exampleFix":"// before\npublic int Resolve(Source s, Dest d, int dest, ResolutionContext ctx) => (int)ctx.Items[\"factor\"];\nvar dto = mapper.Map<Dest>(src); // throws: Items unavailable\n\n// after\npublic int Resolve(Source s, Dest d, int dest, ResolutionContext ctx) =>\n    ctx.TryGetItems(out var items) && items.TryGetValue(\"factor\", out var f) ? (int)f : 1;\nvar dto = mapper.Map<Dest>(src);","handlingStrategy":"validation","validationCode":"// Always probe with TryGetItems before touching Items:\nif (context.TryGetItems(out var items) && items.TryGetValue(\"factor\", out var f))\n{\n    factor = (int)f;\n}\nelse\n{\n    factor = 1; // safe default when no options callback was supplied\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never read context.Items unconditionally in resolvers/converters; always use TryGetItems.","At call sites that rely on items, pass the options overload mapper.Map<S,D>(src, opts => opts.Items[k] = v).","Treat items as optional and define a fallback so missing items degrade gracefully."],"tags":["context","items","mapping-options","resolver"],"backgroundTag":null,"analyzedSha":"dfa6dd587c5854b4beee5934beb39ba6e9569b84","analyzedAt":"2026-08-13T19:56:33.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}