stride3d/stride · error · ArgumentException
The value "
Error message
The value "
What it means
ToKey is the type-coercion helper for non-generic IDictionary operations on SortedList. If the boxed key object cannot be cast to TKey, it throws ArgumentException explaining the value's type does not match the collection's key type. It first rejects null keys via ArgumentNullException.
Solutions
- Pass keys already of type TKey; parse/convert first (e.g. int.Parse(raw)).
- Use the generic SortedList API directly (Add(TKey, TValue), ContainsKey(TKey)) to get compile-time type safety.
- If the type is dynamic, check key is TKey before invoking the non-generic API.
- Use Convert.ChangeType with invariant culture when raw data is a string representation.
Example fix
// before ((IDictionary)sl).Add(rawValue, value); // rawValue is object/string // after var key = (TKey)Convert.ChangeType(rawValue, typeof(TKey), CultureInfo.InvariantCulture); sl.Add(key, value);
Defensive patterns
Strategy: type-guard
Validate before calling
if (key == null) throw new ArgumentNullException(nameof(key));
if (key is not TKey typedKey)
typedKey = (TKey)Convert.ChangeType(key, typeof(TKey), CultureInfo.InvariantCulture);
sortedList.Add(typedKey, value); Type guard
static bool IsTypedKey(object key) => key is TKey;
Try / catch
try { ((IDictionary)sortedList).Add(key, value); }
catch (ArgumentException ex) when (ex.Message.Contains("isn't of type"))
{ /* convert key to TKey and retry via the generic API */ } Prevention
- Use the generic SortedList API exclusively to keep type safety at compile time.
- Parse strings from config/JSON into TKey before insertion.
- Pattern-match object inputs (key is TKey k) at interop boundaries.
- Avoid the non-generic IDictionary cast unless a legacy API requires it.
When it happens
Trigger: Calling non-generic IDictionary.Add/Contains/Remove (or indexer get/set) with an object that is not TKey, e.g. dict.Add(5, "x") on a SortedList<string,T> boxed as IDictionary.
Common situations: Legacy non-generic IDictionary interop, reflection-based configuration loaders reading values from XML/JSON as strings, data-binding frameworks passing untyped objects.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- The given container does not match the expected type.
- A NodeIndex instance cannot be passed as the value of…
- An element with the same key has already been added.
- An id is both marked as deleted and associated to a key of…
- An item has been added to a collection that does not have a…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/7d7a95c4eef5ad4d.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Collections/SortedList.cs:616
while (left <= right)
{
var guess = (left + right) >> 1;
var cmp = comparer.Compare(table[guess].Key, key);
if (cmp == 0) return guess;
if (cmp < 0) left = guess + 1;
else right = guess - 1;
}
return ~left;
}
private TKey ToKey(object key)
{
ArgumentNullException.ThrowIfNull(key);
if (key is not TKey key1)
throw new ArgumentException("The value \"" + key + "\" isn't of type \"" + typeof(TKey) + "\" and can't be used in this generic collection.", nameof(key));
return key1;
}
private TValue ToValue(object value)
{
if (value is not TValue value1)
throw new ArgumentException("The value \"" + value + "\" isn't of type \"" + typeof(TValue) + "\" and can't be used in this generic collection.", nameof(value));
return value1;
}
internal TKey KeyAt(int index)
{
if (index >= 0 && index < Count)
return table[index].Key;
throw new ArgumentOutOfRangeException(nameof(index));
}
internal TValue ValueAt(int index)View on GitHub (pinned to 96fad776d2)