{"record":{"id":"6598030344d023f8","repo":"stride3d/stride","slug":"unable-to-find-the-graph-corresponding-to-the-base-part","errorCode":null,"errorMessage":"Unable to find the graph corresponding to the base part","messagePattern":"Unable to find the graph corresponding to the base part","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets.Quantum/AssetCompositeHierarchyPropertyGraph.cs","lineNumber":681,"sourceCode":"            }\n        }\n\n        // Register to new base part events\n        foreach (var basePartAsset in newBasePartAsset)\n        {\n            basePartAsset.PartAdded += PartAddedInBaseAsset;\n            basePartAsset.PartRemoved += PartRemovedInBaseAsset;\n        }\n    }\n\n    private void PartAddedInBaseAsset(object? sender, AssetPartChangeEventArgs e)\n    {\n        UpdatingPropertyFromBase = true;\n\n        var baseAsset = (AssetCompositeHierarchy<TAssetPartDesign, TAssetPart>)e.Asset;\n        var newPart = baseAsset.Hierarchy.Parts[e.PartId];\n        var newPartParent = baseAsset.GetParent(newPart.Part);\n        if (Container.TryGetGraph(baseAsset.Id) is not AssetCompositeHierarchyPropertyGraph<TAssetPartDesign, TAssetPart> baseAssetGraph) throw new InvalidOperationException(\"Unable to find the graph corresponding to the base part\");\n\n        foreach (var instanceId in basePartAssets[baseAssetGraph])\n        {\n            // Discard the part if this asset don't want it\n            if (!ShouldAddNewPartFromBase(baseAssetGraph, newPart, newPartParent, instanceId))\n                continue;\n\n            var insertIndex = FindBestInsertIndex(baseAsset, newPart, newPartParent, instanceId, out var instanceParent);\n            if (insertIndex < 0)\n                continue;\n\n            // Now we know where to insert, let's clone the new part.\n            const SubHierarchyCloneFlags flags = SubHierarchyCloneFlags.GenerateNewIdsForIdentifiableObjects | SubHierarchyCloneFlags.RemoveOverrides;\n            var baseHierarchy = CloneSubHierarchies(baseAssetGraph.Container.NodeContainer, baseAssetGraph.Asset, newPart.Part.Id.Yield(), flags, out Dictionary<Guid, Guid> mapping);\n            foreach (var ids in mapping)\n            {\n                // Process only ids that correspond to parts\n                if (!baseHierarchy.Parts.TryGetValue(ids.Value, out var clone))","sourceCodeStart":663,"sourceCodeEnd":699,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets.Quantum/AssetCompositeHierarchyPropertyGraph.cs#L663-L699","documentation":"In AssetCompositeHierarchyPropertyGraph's base-asset change handler, this InvalidOperationException is thrown when Container.TryGetGraph(baseAsset.Id) does not return an AssetCompositeHierarchyPropertyGraph<TAssetPartDesign,TAssetPart>. A part changed in the base asset, but its graph is missing or not a hierarchy graph, so instance parts cannot be propagated. It enforces the invariant that a hierarchy base asset always has a matching hierarchy graph in the container.","triggerScenarios":"Receiving a BaseAssetChanged event whose base asset Id has no graph registered in the container, or whose graph is a different graph type (e.g. a plain AssetPropertyGraph rather than a hierarchy graph).","commonSituations":"Base composite assets (prefab/scene-like assets) deleted or unloaded while derived assets remain; type mismatches after changing an asset's type; partial package loads; corrupted or hand-edited asset files with stale base references.","solutions":["Load/restore the base composite asset so its hierarchy graph is registered in the container","Re-save or recreate the derived asset with a valid base reference","Rebuild the asset database/package to re-register missing graphs","Remove the base linkage from the derived asset if inheritance is no longer wanted"],"exampleFix":"// before\nvar graph = container.TryGetGraph(baseAssetId); // may be null / wrong type\n// after\nvar graph = container.TryGetGraph(baseAssetId);\nif (graph is null) { Console.Error.WriteLine($\"Base asset {baseAssetId} not loaded; skipping propagation\"); return; }","handlingStrategy":"try-catch","validationCode":"var graph = Container.TryGetGraph(baseAsset.Id);\nbool canPropagate = graph is AssetCompositeHierarchyPropertyGraph<TAssetPartDesign, TAssetPart>;","typeGuard":"if (Container.TryGetGraph(baseAsset.Id) is AssetCompositeHierarchyPropertyGraph<TAssetPartDesign, TAssetPart> baseGraph) { /* safe to propagate */ }","tryCatchPattern":"try { HandleBaseChanged(e); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"graph corresponding to the base part\")) { // reload base asset or remove derived asset's base link }","preventionTips":["Keep base composite assets loaded in the same container as derived assets","Do not change an asset's type after other assets derive from it","Rebuild the asset database after manual asset-file edits"],"tags":["dotnet","stride","assets","quantum"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}