dotnet/wpf · error · ArgumentException

SR.KeyCollectionHasInvalidKey

Error message

SR.KeyCollectionHasInvalidKey

What it means

Thrown as ArgumentException from ResourceDictionary.SetKeys when a KeyRecord in the deferred-content key collection has neither a KeyString nor a valid type — i.e. the key is invalid. This is an internal invariant of the BAML deferred-content parser: every key record must carry a usable key.

Solutions

  1. Regenerate/recompile the BAML resource (rebuild the assembly)
  2. Ensure any custom XAML reader sets either KeyString or a valid key type on every KeyRecord
  3. Verify the assembly's .baml resources are not corrupted or tampered with
Defensive patterns

Strategy: validation

Validate before calling

foreach (var k in keyRecords) { if (k?.KeyString == null && k?.KeyType == null) throw new ArgumentException("Invalid key record"); }

Try / catch

try { dict.DeferrableContent = content; } catch (ArgumentException ex) { /* log malformed BAML, rebuild resources */ }

Prevention

When it happens

Trigger: Deferred BAML content whose key collection contains a KeyRecord with null KeyString and no recognized key type (e.g. corrupted or hand-built key records passed to SetKeys).

Common situations: Custom XAML reader implementations producing malformed key records; corrupted compiled BAML resources; rarely hit by ordinary application code.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/23a92f3fbaf7fe81. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ResourceDictionary.cs:1296

                    if (keyRecord != null && keyRecord.HasStaticResources)
                    {
                        SetOptimizedStaticResources(keyRecord.StaticResources, serviceProvider, staticResourceWorker);
                    }

                    _baseDictionary.Add(value, keyRecord);

                    if (TraceResourceDictionary.IsEnabled)
                    {
                        TraceResourceDictionary.TraceActivityItem(
                            TraceResourceDictionary.SetKey,
                            this,
                            value);
                    }

                }
                else
                {
                    throw new ArgumentException(SR.KeyCollectionHasInvalidKey);
                }
            }

            // Notify owners of the HasImplicitStyles flag value
            // but there is not need to fire an invalidation.
            NotifyOwners(new ResourcesChangeInfo(null, this));
        }

        /// <summary>
        /// Convert the OptimizedStaticResource and StaticResource items into StaticResourceHolders.
        /// A StaticResourceHolder is derived from StaticResourceExtension and is a MarkupExtension.
        /// The differences is that it contain a DeferredResourceReference as its "PrefetchedValue".
        /// DeferredResourceReferences hold the dictionary and the key of the resource.  It is a
        /// way of looking up the reference now (for later use) but not expanding the entry.
        /// Also the dictionary has a reference back to the Deferrred Reference.  If dictionary entry
        /// is modifed the DeferredResourceReference is told and it will grab the old value.
        /// StaticResourceHolder is a MarkupExtension and thus can be returned as a "Value" in the Node Stream.
        ///

View on GitHub (pinned to 81131a70a4)