Skip to content

Fix crash with container elements in spinner context#13659

Merged
sfc-gh-kmcgrady merged 4 commits intodevelopfrom
kmcgrady/fix-delta-path-visitor
Jan 21, 2026
Merged

Fix crash with container elements in spinner context#13659
sfc-gh-kmcgrady merged 4 commits intodevelopfrom
kmcgrady/fix-delta-path-visitor

Conversation

@sfc-gh-kmcgrady
Copy link
Copy Markdown
Contributor

@sfc-gh-kmcgrady sfc-gh-kmcgrady commented Jan 21, 2026

Describe your changes

Fix a regression where creating container elements (st.columns, st.tabs) inside a container within a st.spinner context caused the app to crash with "Bad delta path index" errors.

The root cause was that SetNodeByDeltaPathVisitor.visitTransientNode incorrectly consumed an index from the delta path when visiting TransientNodes, while GetNodeByDeltaPathVisitor correctly treats them as transparent. This caused delta paths to become misaligned with the actual tree structure.

The fix treats TransientNode as transparent in the delta path hierarchy and preserves the transient wrapper when modifying nodes inside its anchor.

GitHub Issue Link (if applicable)

Closes #13658

Testing Plan

  • Unit Tests (JS): Updated and added tests for SetNodeByDeltaPathVisitor.visitTransientNode to verify the fix
  • E2E Tests: Added regression test test_spinner_with_container_elements that reproduces the exact scenario from the issue
  • All 5630 frontend tests pass
  • All 201 render-tree tests pass

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

…ners in spinner

The SetNodeByDeltaPathVisitor was incorrectly consuming an index from the delta
path when visiting a TransientNode, causing a mismatch between expected and
actual tree structure. This led to "Bad delta path index" errors when creating
container elements (st.columns, st.tabs) inside a st.spinner context.

The fix treats TransientNode as transparent in the delta path hierarchy (matching
the behavior of GetNodeByDeltaPathVisitor) and preserves the transient wrapper
when modifying nodes inside its anchor.

Closes #13658

Co-Authored-By: Claude <[email protected]>
Copilot AI review requested due to automatic review settings January 21, 2026 15:38
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 21, 2026

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-13659/streamlit-1.53.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-13659.streamlit.app (☁️ Deploy here if not accessible)

@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Jan 21, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@sfc-gh-kmcgrady sfc-gh-kmcgrady added the ai-review If applied to PR or issue will run AI review workflow label Jan 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression causing app crashes when creating container elements (like st.columns or st.tabs) inside a container within a st.spinner context. The crash manifested as "Bad delta path index" errors.

Changes:

  • Fixed SetNodeByDeltaPathVisitor.visitTransientNode to treat TransientNode as transparent in the delta path hierarchy (not consuming an index), matching the behavior of GetNodeByDeltaPathVisitor
  • Updated and expanded tests to verify the fix and prevent regression

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
frontend/lib/src/render-tree/visitors/SetNodeByDeltaPathVisitor.ts Fixed visitTransientNode to not consume delta path index and preserve transient wrapper when drilling through anchor
frontend/lib/src/render-tree/visitors/SetNodeByDeltaPathVisitor.test.ts Updated existing tests to reflect new behavior and added comprehensive test for the bug scenario

@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Jan 21, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR fixes a regression (#13658) where creating container elements (st.columns, st.tabs) inside a container within an st.spinner context caused the app to crash with "Bad delta path index" errors. The root cause was an inconsistency between how SetNodeByDeltaPathVisitor and GetNodeByDeltaPathVisitor handle TransientNode traversal.

Key Changes:

  • SetNodeByDeltaPathVisitor.visitTransientNode now treats TransientNode as transparent in the delta path hierarchy (matching GetNodeByDeltaPathVisitor)
  • The fix ensures TransientNode doesn't consume an index from the path when drilling through to its anchor
  • The transient wrapper is now preserved when modifying nodes inside its anchor

Code Quality

The implementation is clean and well-documented:

Strengths:

  • The fix is minimal and precisely targeted to the bug
  • Clear comments explain the intended behavior (lines 69-71 in SetNodeByDeltaPathVisitor.ts)
  • The new logic correctly mirrors GetNodeByDeltaPathVisitor.visitTransientNode for consistency
  • Immutability is maintained by creating a new TransientNode with the modified anchor

Analysis of the fix:

The old code incorrectly consumed the first path index:

const [, ...remainingPath] = this.deltaPath  // Bug: consumed an index

The new code passes through transparently:

const newAnchor = node.anchor.accept(this)  // Correct: same path, no index consumed

This aligns with GetNodeByDeltaPathVisitor (lines 74-76) which uses node.anchor?.accept(this) without modifying the path.

Test Coverage

The test coverage is thorough and appropriate:

Updated Tests:

  1. "drills through anchor without consuming path index and preserves transient wrapper" - Correctly updated to use path [0] instead of [0, 0] and now verifies the TransientNode wrapper preservation
  2. "throws when drilling required but no anchor exists" - Updated to use path [0] instead of [0, 1]
  3. "delegates to nodeToSet.replaceTransientNodeWithSelf when path is empty" - Updated to use empty path [] instead of [0]

New Test:
4. "preserves transient nodes when setting deep inside anchor" (lines 547-578) - Excellent new test that directly reproduces the bug scenario: adding children to a container wrapped in a TransientNode

The tests follow TypeScript best practices:

  • Uses it.each for parameterized tests where applicable
  • Includes both positive and negative assertions
  • Tests verify the specific bug scenario (transient nodes preserved when adding children)
  • Uses appropriate matchers (toBeInstanceOf, toEqual, toHaveLength)

E2E Test Gap: There is no E2E test for this specific scenario, but given this is a frontend-only fix with comprehensive unit tests, the coverage appears adequate. The original issue is reproducible via manual testing per the issue description.

Backwards Compatibility

No breaking changes. This is a pure bug fix that:

  • Brings SetNodeByDeltaPathVisitor in line with the already-established behavior of GetNodeByDeltaPathVisitor
  • Fixes a crash scenario without changing intended functionality
  • Does not modify any public APIs

The change corrects behavior that was causing crashes, making it a strict improvement.

Security & Risk

Security: No security concerns identified. The changes are localized to tree traversal logic with no impact on data handling, authentication, or external communication.

Risk Assessment: Low risk.

  • The fix is well-scoped to TransientNode handling in SetNodeByDeltaPathVisitor
  • Unit tests comprehensively cover the changed behavior
  • The fix addresses a clear regression from v1.53.0
  • The PR author confirms all 5630 frontend tests pass

Recommendations

No critical issues found. Minor suggestions:

  1. Consider adding an E2E test - While the unit tests are comprehensive, an E2E test matching the reproduction steps from issue App goes blank when creating element (st.tabs, st.columns) within a container in a spinner context #13658 would provide additional confidence:

    with st.spinner("Running..."):
        time.sleep(0.1)  # Small delay to trigger spinner rendering
        st.container().columns(2)

    This is optional given the thorough unit test coverage.

  2. Documentation is sufficient - The PR description clearly explains the root cause and fix. The inline code comments adequately document the intended behavior.

Verdict

APPROVED: This is a well-implemented bug fix that correctly addresses the regression by making SetNodeByDeltaPathVisitor treat TransientNode consistently with GetNodeByDeltaPathVisitor. The fix is minimal, well-tested, and backwards compatible.


This is an automated AI review using opus-4.5-thinking. Please verify the feedback and use your judgment.

kmcgrady and others added 3 commits January 21, 2026 07:58
Regression test for issue #13658: verifies that creating container
elements (st.columns) inside a st.spinner context doesn't crash the app.

Co-Authored-By: Claude <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

📈 Frontend coverage change detected

The frontend unit test (vitest) coverage has increased by 0.0500%

  • Current PR: 86.4500% (13339 lines, 1807 missed)
  • Latest develop: 86.4000% (13339 lines, 1814 missed)

🎉 Great job on improving test coverage!

📊 View detailed coverage comparison

Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

@sfc-gh-kmcgrady sfc-gh-kmcgrady merged commit 236d277 into develop Jan 21, 2026
44 of 46 checks passed
@sfc-gh-kmcgrady sfc-gh-kmcgrady deleted the kmcgrady/fix-delta-path-visitor branch January 21, 2026 22:20
github-actions bot pushed a commit that referenced this pull request Jan 22, 2026
## Describe your changes

Fix a regression where creating container elements (`st.columns`,
`st.tabs`) inside a container within a `st.spinner` context caused the
app to crash with "Bad delta path index" errors.

The root cause was that `SetNodeByDeltaPathVisitor.visitTransientNode`
incorrectly consumed an index from the delta path when visiting
TransientNodes, while `GetNodeByDeltaPathVisitor` correctly treats them
as transparent. This caused delta paths to become misaligned with the
actual tree structure.

The fix treats TransientNode as transparent in the delta path hierarchy
and preserves the transient wrapper when modifying nodes inside its
anchor.

## GitHub Issue Link (if applicable)

Closes #13658

## Testing Plan

- Unit Tests (JS): Updated and added tests for
`SetNodeByDeltaPathVisitor.visitTransientNode` to verify the fix
- E2E Tests: Added regression test
`test_spinner_with_container_elements` that reproduces the exact
scenario from the issue
- All 5630 frontend tests pass
- All 201 render-tree tests pass

---

**Contribution License Agreement**

By submitting this pull request you agree that all contributions to this
project are made under the Apache 2.0 license.

---------

Co-authored-by: Ken McGrady <[email protected]>
Co-authored-by: Claude <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:bugfix PR contains bug fix implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

App goes blank when creating element (st.tabs, st.columns) within a container in a spinner context

4 participants