{"record":{"id":"03efb64b5a940455","repo":"dotnet/wpf","slug":"throw-new-invalidoperationexception-sr-format-sr-frugalmap","errorCode":null,"errorMessage":"throw new InvalidOperationException(SR.Format(SR.FrugalMap_CannotPromoteBeyondHashtable));","messagePattern":"throw new InvalidOperationException\\(SR\\.Format\\(SR\\.FrugalMap_CannotPromoteBeyondHashtable\\)\\);","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalMap.cs","lineNumber":1640,"sourceCode":"            }\n        }\n\n        public override void Iterate(ArrayList list, FrugalMapIterationCallback callback)\n        {\n            foreach (KeyValuePair<int, object> entry in _entries)\n            {\n                object value = (entry.Value != NullValue) ?\n                    entry.Value :\n                    DependencyProperty.UnsetValue;\n            \n                callback(list, entry.Key, value);\n            }\n        }\n\n        public override void Promote(FrugalMapBase newMap)\n        {\n            // Should never get here\n            throw new InvalidOperationException(SR.Format(SR.FrugalMap_CannotPromoteBeyondHashtable));\n        }\n\n        // Size of this data store\n        public override int Count\n        {\n            get\n            {\n                return _entries.Count;\n            }\n        }\n\n        // 163 is chosen because it is the first prime larger than 128, the MAXSIZE of SortedObjectMap\n        internal const int MINSIZE = 163;\n\n        // Hashtable will return null from its indexer if the key is not\n        // found OR if the value is null.  To distinguish between these\n        // two cases we insert NullValue instead of null.\n        private static object NullValue = new object();","sourceCodeStart":1622,"sourceCodeEnd":1658,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalMap.cs#L1622-L1658","documentation":"HashObjectMap is the terminal store in the FrugalMap promotion chain, so its Promote override is unreachable and unconditionally throws InvalidOperationException('Cannot promote beyond Hashtable'). Hitting it means the promotion logic attempted to grow an already-maximal store.","triggerScenarios":"Calling Promote directly on a HashObjectMap store, or internal code paths that select HashObjectMap as a promotion target instead of the terminal store.","commonSituations":"Only during custom storage experiments or WPF framework bugs; application code never calls store Promote directly since FrugalMap.InsertEntry manages store selection.","solutions":["Never call Promote on a HashObjectMap — it is the largest store tier","Check FrugalMapStoreState before choosing a promotion target","If thrown inside stock WPF, file a bug with the call stack"],"exampleFix":"// before\nhashMapStore.Promote(nextStore); // always throws\n// after\nif (hashMapStore is not HashObjectMap) hashMapStore.Promote(nextStore);","handlingStrategy":"type-guard","validationCode":"if (store is HashObjectMap) { /* terminal store: do not promote */ return; }","typeGuard":"bool IsTerminalStore(FrugalMapBase store) => store is HashObjectMap;","tryCatchPattern":"try { store.Promote(next); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"Hashtable\")) { /* already at max tier */ }","preventionTips":["Know the promotion chain ends at HashObjectMap","Never target HashObjectMap as a promotion destination","Let FrugalMap.InsertEntry pick the store"],"tags":["wpf","frugalmap","invalidoperationexception","promotion","unsupported"],"backgroundTag":"unsupported-operation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}