SG-45127 Fix AttributeError in ShotgunHierarchyModel when first path is not loaded - #180
Open
stevelittlefish wants to merge 2 commits into
Open
SG-45127 Fix AttributeError in ShotgunHierarchyModel when first path is not loaded#180stevelittlefish wants to merge 2 commits into
stevelittlefish wants to merge 2 commits into
Conversation
…is not loaded async_item_from_paths crashed with "AttributeError: 'NoneType' object has no attribute 'index'" whenever the first path in the list was not yet loaded in the model (e.g. the Loader auto-navigating home during __init__ before the root's children are fetched). Two related defects in shotgun_hierarchy_model.py: - async_item_from_paths sliced paths[idx - 1:] to hand _NodeRefresher an already loaded ancestor plus the awaited node. For idx == 0 that wrapped to paths[-1:] (the deepest, never-loaded path). The first path's real parent is the model root (self._path), which always exists, so refresh from there when idx == 0. - _NodeRefresher.__init__ dereferenced item_from_path(path_to_refresh[0]).index() unconditionally. Guard against item_from_path() returning None and abort the refresh gracefully instead of crashing. Adds a regression test that drives the idx == 0 branch and asserts it no longer raises. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #180 +/- ##
==========================================
+ Coverage 61.63% 62.32% +0.69%
==========================================
Files 50 50
Lines 3412 3419 +7
==========================================
+ Hits 2103 2131 +28
+ Misses 1309 1288 -21
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…rarchy-model-nonetype
stevelittlefish
marked this pull request as ready for review
September 4, 2026 15:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
ShotgunHierarchyModel.async_item_from_pathsraisedAttributeError: 'NoneType' object has no attribute 'index'whenever the first path in the list was not yet loaded in the model. This happens, for example, when an app such as the Loader auto-navigates to an entity while the model's root children have not been fetched yet. Reference: SG-45127.Root cause
Two related defects in
shotgun_hierarchy_model.py:async_item_from_pathsslicedpaths[idx - 1:]to hand_NodeRefresheran already-loaded ancestor at index 0 plus the awaited node at index 1. Foridx == 0this wrapped topaths[-1:]— the deepest, never-loaded path. The loop implicitly assumed the first path is always already loaded._NodeRefresher.__init__then calledmodel.item_from_path(path_to_refresh[0]).index()unconditionally. Fed the deepest path by defect 1,item_from_path()returnedNoneand.index()raised.Fix
When
idx == 0, refresh from the model root (self._path) — the first path's real parent, which always exists — instead of wrapping to the deepest path.Guard
_NodeRefresher.__init__againstitem_from_path()returningNone, aborting the refresh gracefully rather than crashing.Testing
Added
test_async_item_from_paths_first_path_not_loaded, which drives theidx == 0branch and asserts it no longer raises.Verified against the real model code that the previous logic crashed with the reported
AttributeErrorwhile the updated logic refreshes from the root instead (nothing-loaded state aborts gracefully via the guard; root-loaded state issues afetchMoreon the root).