stride3d/stride · error · InvalidOperationException

The path [ ] contains a null key on an dictionary.

Error message

The path [{ToString()}] contains a null key on an dictionary.

What it means

Thrown by YamlAssetPath.ToMemberPath when a path element targeting a dictionary has a null key. Dictionary entries are addressed by their key, and a null key cannot select any entry, so the library fails fast instead of pushing an invalid MemberPath node.

Solutions

  1. Fix the dictionary key in the asset YAML to the actual non-null key value
  2. Correct the code building the YamlAssetPath to reject/skip null keys before pushing them
  3. Change dictionary key types so nulls cannot occur (value-type keys)
  4. Guard callers of ToMemberPath with a try/catch on InvalidOperationException and log the full path

Example fix

// before
path.Push(dictDescriptor, someKey); // someKey == null
// after
if (someKey != null) path.Push(dictDescriptor, someKey);
Defensive patterns

Strategy: validation

Validate before calling

if (pathItem.Value is null) throw new ArgumentException("Dictionary keys cannot be null in asset paths");

Type guard

bool IsValidDictKey(object v) => v != null;

Try / catch

try { memberPath = yamlPath.ToMemberPath(); } catch (InvalidOperationException ex) { log.Error($"Null dict key in '{yamlPath}': {ex.Message}"); }

Prevention

When it happens

Trigger: ToMemberPath resolves the current object to a DictionaryDescriptor and the next path element's Value is null.

Common situations: Hand-edited YAML leaving an empty dictionary key; a serializer writing null for a key of a type that permits nulls; programmatic path construction passing null for an unassigned key variable.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/8e95ae9efef48619. Report an issue: GitHub.

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/Yaml/YamlAssetPath.cs:282

                                {
                                    throw new InvalidOperationException($"The path [{ToString()}] item doesn't exsit on a set.");
                                }
                                memberPath.Push(setDescriptor, item.Value);
                                currentObject = item.Value;
                            }
                            else
                            {
                                if (item.Value is not int)
                                {
                                    throw new InvalidOperationException($"The path [{ToString()}] contains non-integer index on a collection.");
                                }
                                memberPath.Push(collectionDescriptor, item.Value);
                                currentObject = collectionDescriptor.GetValue(currentObject, item.Value);
                            }
                        }
                        else if (typeDescriptor is DictionaryDescriptor dictionaryDescriptor)
                        {
                            if (item.Value is null) throw new InvalidOperationException($"The path [{ToString()}] contains a null key on an dictionary.");
                            memberPath.Push(dictionaryDescriptor, item.Value);
                            currentObject = dictionaryDescriptor.GetValue(currentObject, item.Value);
                        }
                        break;
                    }
                case ElementType.ItemId:
                    {
                        var ids = CollectionItemIdHelper.GetCollectionItemIds(currentObject);
                        var key = ids.GetKey(item.AsItemId());
                        var typeDescriptor = TypeDescriptorFactory.Default.Find(currentObject.GetType());
                        if (typeDescriptor is ArrayDescriptor arrayDescriptor)
                        {
                            if (key is not int) throw new InvalidOperationException($"The path [{ToString()}] contains a non-valid item id on an array.");
                            int keyInt = (int)key;
                            memberPath.Push(arrayDescriptor, keyInt);
                            currentObject = arrayDescriptor.GetValue(currentObject, keyInt);
                        }
                        else if (typeDescriptor is CollectionDescriptor collectionDescriptor)

View on GitHub (pinned to 96fad776d2)