stride3d/stride · error · InvalidOperationException
The path [ ] contains a non-valid item id on a collection.
Error message
The path [{ToString()}] contains a non-valid item id on a collection. What it means
Thrown by YamlAssetPath.ToMemberPath when an ItemId path element resolves against a list (non-set collection) but the key derived from the item id is not an integer. Lists are position-based, so only integer keys are valid; a non-int key means the id is stale or was produced for a keyed container.
Solutions
- Re-save the asset so list paths are stored as integer indices/item ids matching the current container type
- Migrate the container type or the stored path when refactoring a property between list and set/dictionary
- Remove and re-create the affected reference in the editor
- Catch InvalidOperationException around ToMemberPath and re-link broken references programmatically
Example fix
// before myList: !AssetRef itemId="0a1b-..." // after myList: index: 0
Defensive patterns
Strategy: type-guard
Validate before calling
var key = ids.GetKey(itemId); if (isList && key is not int) throw new ArgumentException("List item ids must resolve to int keys"); Type guard
bool IsIntListItemId(object key) => key is int;
Try / catch
try { memberPath = yamlPath.ToMemberPath(); } catch (InvalidOperationException) { RebuildPathFromObjectGraph(asset, yamlPath); } Prevention
- Migrate stored paths after changing a property between HashSet and List
- Re-save assets when container types change so ids match the id map
- Avoid hand-editing item-id sections of asset YAML
- Run an asset-reference health check after major refactors
When it happens
Trigger: In the ElementType.ItemId branch, currentObject's descriptor is a CollectionDescriptor with Category != Set and the resolved key is not int (e.g. a Guid or string from a previous set/dictionary representation).
Common situations: Container type changed between asset versions (e.g. HashSet<T> changed to List<T> or vice versa), leaving GUID-style ids in paths against lists; duplicated/merged assets; hand-edited YAML.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- The path [ ] contains non-integer index on a collection.
- The path [ ] contains a non-valid item id on an array.
- The path [ ] contains a non-valid item id on an dictionary.
- The given container does not match the expected type.
- The path [ ] contains non-integer index on an array.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/5a8d2332f745fd12.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/Yaml/YamlAssetPath.cs:313
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)
{
if (collectionDescriptor.Category == DescriptorCategory.Set)
{
if (item.Value is null && !collectionDescriptor.ElementType.IsNullable())
{
throw new InvalidOperationException($"The path [{ToString()}] contains a null item on a set.");
}
}
else
{
if (key is not int)
{
throw new InvalidOperationException($"The path [{ToString()}] contains a non-valid item id on a collection.");
}
}
memberPath.Push(collectionDescriptor, key);
currentObject = collectionDescriptor.GetValue(currentObject, key);
}
else if (typeDescriptor is DictionaryDescriptor dictionaryDescriptor)
{
if (key is null) throw new InvalidOperationException($"The path [{ToString()}] contains a non-valid item id on an dictionary.");
memberPath.Push(dictionaryDescriptor, key);
currentObject = dictionaryDescriptor.GetValue(currentObject, key);
}
break;
}
default:
throw new ArgumentOutOfRangeException();
}
}
View on GitHub (pinned to 96fad776d2)