Blueprints are cleared in SDK v3.10.4
玖渚 颯
After the Blueprint ID was removed, the SDK panel was rebuilt, and the avatar switching process—which was executed with a delay—was searching for a VisualElement that had already been discarded.
I added a guard to abort the process if the panel was disconnected, and confirmed that compilation succeeded under the same conditions as the VRChat SDK.
Since I couldn't attach the patch, I've included it in the MD file.
Log In
玖渚 颯
blueprint-sdk-ui-guard.diff
--- a/Packages/com.vrchat.avatars/Editor/VRCSDK/SDK3A/VRCSdkControlPanelAvatarBuilder.cs
+++ b/Packages/com.vrchat.avatars/Editor/VRCSDK/SDK3A/VRCSdkControlPanelAvatarBuilder.cs
@@ -1625,12 +1625,26 @@ namespace VRC.SDK3A.Editor
// We want to avoid any background operations while building
if (VRCMultiPlatformBuild.MPBState == VRCMultiPlatformBuild.MultiPlatformBuildState.Building) return;
+ // A delayed avatar-selection callback can outlive the SDK panel that created it.
+ // Querying a detached visual tree can make UI Toolkit traverse disposed children.
+ if (root == null || root.panel == null) return;
+
_visualRoot = root;
// Cancel all ongoing ops
_avatarSwitchCancellationToken.Cancel();
_avatarSwitchCancellationToken = new CancellationTokenSource();
- var platformsBlock = root.Q<Label>("content-platform-info");
+ Label platformsBlock;
+ try
+ {
+ platformsBlock = root.Q<Label>("content-platform-info");
+ }
+ catch (NullReferenceException)
+ {
+ // Unity 2022 can throw internally while a visual tree is being detached.
+ return;
+ }
+ if (platformsBlock == null) return;
// Unregister all the callbacks to avoid multiple calls
_nameField.UnregisterCallback<ChangeEvent<string>>(HandleNameChange);
玖渚 颯
## Suspected sequence
- Open a scene containing an avatar whose PipelineManager.blueprintIdbelongs to another account.
- Sign in to the SDK with an account that does not own that avatar.
- Open the SDK avatar panel and select the avatar.
- ClearAvatarDataclears the blueprint ID after the ownership check.
- Close, rebuild, or otherwise refresh the SDK panel while avatar selection is updating.
- A delayed HandleAvatarSwitch(root)invocation reachesroot.Q<Label>("content-platform-info")after the root has been detached.
The timing appears race-dependent, so the exception may not occur on every attempt.
## Code locations
- Blueprint ownership handling and clearing: VRCSdkControlPanelAvatarBuilder.ClearAvatarData, around lines 1857-1868.
- Failing visual-tree query: VRCSdkControlPanelAvatarBuilder.HandleAvatarSwitch, around line 1633.
- HandlePanelDetachcancels scene event handling, but does not appear to invalidate all already queuedHandleAvatarSwitchcalls.
## Proposed defensive fix
Before querying the root, return if it is null or detached. Unity 2022 can still throw internally while detachment is in progress, so the attached patch also guards the query itself and verifies that the requested element exists.
Patch:
blueprint-sdk-ui-guard.diff
The patch is intended as a minimal reproduction workaround. A preferred upstream fix may instead cancel or version all pending avatar-switch operations when
HandlePanelDetach
runs, ensuring that a callback cannot outlive the panel that created it.玖渚 颯
NullReferenceException in HandleAvatarSwitch after a non-owned avatar blueprint ID is cleared
## Environment
- Unity: 2022.3.22f1 (887be4894c44)
- VRChat SDK - Avatars: 3.10.4
- VRChat SDK - Base: 3.10.4
- Platform: Windows
## Summary
When the SDK loads an avatar blueprint that is not owned by the currently authenticated account, it correctly clears
PipelineManager.blueprintId
. During or shortly after the resulting avatar-selection/UI refresh, a delayed HandleAvatarSwitch
call can receive a VisualElement root whose panel has already been detached. root.Q<Label>()
then traverses the invalid visual tree and throws a NullReferenceException
inside UI Toolkit.## Observed behavior
The SDK first logs:
```text
Loaded data for an avatar we do not own, clearing blueprint ID
It can then log:
```text
NullReferenceException: Object reference not set to an instance of an object
at UnityEngine.UIElements.StyleSheets.HierarchyTraversal.Recurse (UnityEngine.UIElements.VisualElement element, System.Int32 depth)
at UnityEngine.UIElements.UQuery+UQueryMatcher.TraverseRecursive (UnityEngine.UIElements.VisualElement element, System.Int32 depth)
at UnityEngine.UIElements.StyleSheets.HierarchyTraversal.Traverse (UnityEngine.UIElements.VisualElement element)
at UnityEngine.UIElements.UQuery+UQueryMatcher.Traverse (UnityEngine.UIElements.VisualElement element)
at UnityEngine.UIElements.UQuery+UQueryMatcher.Run (UnityEngine.UIElements.VisualElement root, System.Collections.Generic.List`1[T] matchers)
at UnityEngine.UIElements.UQuery+SingleQueryMatcher.Run (UnityEngine.UIElements.VisualElement root, System.Collections.Generic.List`1[T] matchers)
at UnityEngine.UIElements.UQueryState`1[T].Single (UnityEngine.UIElements.UQuery+SingleQueryMatcher matcher)
at UnityEngine.UIElements.UQueryState`1[T].First ()
at UnityEngine.UIElements.UQueryExtensions.Q[T] (UnityEngine.UIElements.VisualElement e, System.String name, System.String className)
at VRC.SDK3A.Editor.VRCSdkControlPanelAvatarBuilder.HandleAvatarSwitch (UnityEngine.UIElements.VisualElement root)
(at Packages/com.vrchat.avatars/Editor/VRCSDK/SDK3A/VRCSdkControlPanelAvatarBuilder.cs:1633)
## Expected behavior
The non-owned blueprint ID is cleared without an exception. Any delayed avatar-selection callback associated with a detached SDK panel should be cancelled or ignored.
玖渚 颯
Since I can't upload an .md file, I'll paste the text here.