stride3d/stride · error · InvalidOperationException

No Collection item identifier associated to the given…

Error message

No Collection item identifier associated to the given collection.

What it means

AssetObjectNodeExtended tracks collection item identities (CollectionItemIdentifiers) attached to a Quantum node. IsItemDeleted needs the id registry for the node's retrieved collection to check whether a given ItemId is deleted; if the retrieved instance has no associated CollectionItemIdentifiers, the invariant is broken and it throws InvalidOperationException.

Solutions

  1. Ensure the collection actually has collection item identifiers (no NonIdentifiableCollectionItemsAttribute) and that asset metadata was loaded/upgraded so ids exist before querying IsItemDeleted.
  2. Use TryGetCollectionItemIds / TryIdToIndex-style checks (or CollectionItemIdHelper.HasCollectionItemIds) to verify ids exist before calling IsItemDeleted.
  3. Verify the node passed in is the AssetObjectNode for a collection with identifiable items, not a different node type.
  4. Re-save/migrate the asset so its collection ids metadata is regenerated.

Example fix

// before
bool deleted = nodeExtended.IsItemDeleted(itemId);
// after
if (CollectionItemIdHelper.HasCollectionItemIds(nodeExtended.Node.Retrieve()))
    deleted = nodeExtended.IsItemDeleted(itemId);
else
    deleted = false; // treat as non-identifiable collection
Defensive patterns

Strategy: validation

Validate before calling

bool canQuery = CollectionItemIdHelper.HasCollectionItemIds(nodeExtended.Node.Retrieve());
if (!canQuery) return false; // non-identifiable collection: no deleted ids

Type guard

static bool HasItemIds(AssetObjectNodeExtended n) =>
    CollectionItemIdHelper.HasCollectionItemIds(n.Node.Retrieve());

Try / catch

try { deleted = nodeExtended.IsItemDeleted(itemId); }
catch (InvalidOperationException) { deleted = false; // ids missing }

Prevention

When it happens

Trigger: Calling IsItemDeleted (directly or via IsItemOverriddenDeleted) on a node whose Retrieve() returns an object for which TryGetCollectionItemIds fails — i.e. the node's collection has no collection-item-ids metadata (non-identifiable collection, metadata not yet attached, or node type changed).

Common situations: Querying deleted-item state on collections not marked identifiable; calling during partial deserialization before ids are attached; passing a node wrapping a non-collection or a collection stripped of its NonIdentifiableCollectionItemsAttribute metadata; asset edit-vs-base mismatch after type changes.

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 stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/b152a41637e228eb. Report an issue: GitHub.

Appendix: source

Thrown at sources/assets/Stride.Core.Assets.Quantum/Internal/AssetObjectNodeExtended.cs:106

            }
            node.NotifyOverrideChanged();
        }
    }

    public void DisconnectOverriddenDeletedItem(ItemId deletedId)
    {
        disconnectedDeletedIds.Add(deletedId);
        OverrideDeletedItem(false, deletedId);
    }

    public bool IsItemDeleted(ItemId itemId)
    {
        if (disconnectedDeletedIds.Contains(itemId))
            return true;

        var collection = node.Retrieve();
        if (!TryGetCollectionItemIds(collection, out var ids))
            throw new InvalidOperationException("No Collection item identifier associated to the given collection.");
        return ids.IsDeleted(itemId);
    }

    private bool TryGetCollectionItemIds(object? instance, [MaybeNullWhen(false)] out CollectionItemIdentifiers itemIds)
    {
        if (collectionItemIdentifiers is not null)
        {
            itemIds = collectionItemIdentifiers;
            return true;
        }

        var result = CollectionItemIdHelper.TryGetCollectionItemIds(instance, out collectionItemIdentifiers);
        itemIds = collectionItemIdentifiers;
        return result;
    }

    public void Restore(object restoredItem, ItemId id)
    {

View on GitHub (pinned to 96fad776d2)