Skip to content

fix(vega-lite): render vconcat charts with faceted/repeated children#14065

Merged
sfc-gh-bnisco merged 1 commit intodevelopfrom
02-22-fix_vega-lite_render_vconcat_charts_with_faceted_repeated_children
Feb 23, 2026
Merged

fix(vega-lite): render vconcat charts with faceted/repeated children#14065
sfc-gh-bnisco merged 1 commit intodevelopfrom
02-22-fix_vega-lite_render_vconcat_charts_with_faceted_repeated_children

Conversation

@sfc-gh-bnisco
Copy link
Copy Markdown
Collaborator

@sfc-gh-bnisco sfc-gh-bnisco commented Feb 22, 2026

Describe your changes

Fixed a regression where Vega-Lite charts with vconcat containing faceted or repeated children would fail to render with "infinite extent" errors when using width="stretch". The issue occurred because the width preprocessing logic only checked for composition operators (hconcat, vconcat, concat, layer) but not for multi-view compositions (facet, repeat).

Updated the nested composition detection logic in both frontend and backend to include facet and repeat operators, ensuring these chart types use pad autosize instead of fit-x to prevent rendering errors.

GitHub Issue Link (if applicable)

Fixes #14050

Testing Plan

  • Unit Tests (JS and/or Python): Added test cases for facet and repeat detection in both frontend (ArrowVegaLiteChart.test.tsx, useVegaElementPreprocessor.test.ts) and backend (vega_charts_test.py)
  • E2E Tests: Added regression test test_vconcat_layered_facet_regression_renders that verifies the chart renders correctly and contains visible graphics elements

Contribution License Agreement

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

@sfc-gh-bnisco sfc-gh-bnisco added the change:bugfix PR contains bug fix implementation label Feb 22, 2026 — with Graphite App
@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Feb 22, 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-bnisco sfc-gh-bnisco added the impact:users PR changes affect end users label Feb 22, 2026 — with Graphite App
Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 22, 2026

✅ PR preview is ready!

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

@sfc-gh-bnisco sfc-gh-bnisco added the ai-review If applied to PR or issue will run AI review workflow label Feb 22, 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

Fixes a Vega-Lite rendering regression in Streamlit where vconcat charts containing facet or repeat children could fail with “infinite extent” errors when using width="stretch", by expanding nested-composition detection so these charts use safer autosizing behavior.

Changes:

  • Extend nested composition detection to include facet and repeat in both Python and TypeScript.
  • Add backend + frontend unit tests covering facet/repeat detection and sizing behavior.
  • Add an E2E regression scenario for issue #14050 and assert the chart renders visible graphics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lib/streamlit/elements/vega_charts.py Backend nested-composition detection updated to include facet/repeat for autosize decisions.
lib/tests/streamlit/elements/vega_charts_test.py Adds backend tests for nested composition detection and autosize behavior with faceted children.
frontend/lib/src/components/elements/ArrowVegaLiteChart/useVegaElementPreprocessor.ts Frontend preprocessing skips forcing child widths for facet/repeat vconcat children to avoid “infinite extent”.
frontend/lib/src/components/elements/ArrowVegaLiteChart/useVegaElementPreprocessor.test.ts Adds unit tests ensuring widths are skipped for facet/repeat children.
frontend/lib/src/components/elements/ArrowVegaLiteChart/ArrowVegaLiteChart.tsx Updates nested-composition detection to treat facet/repeat as nested compositions.
frontend/lib/src/components/elements/ArrowVegaLiteChart/ArrowVegaLiteChart.test.tsx Adds unit tests for facet/repeat nested composition detection.
e2e_playwright/st_altair_chart.py / e2e_playwright/st_altair_chart_test.py Adds and validates an E2E regression chart for issue #14050 rendering.
Comments suppressed due to low confidence (2)

frontend/lib/src/components/elements/ArrowVegaLiteChart/useVegaElementPreprocessor.ts:175

  • generateSpec assumes spec.vconcat is an array and calls spec.vconcat.forEach(...) after only checking "vconcat" in spec. If a malformed spec sets vconcat to a non-array value, this will throw at runtime in the preprocessor. Consider guarding with Array.isArray(spec.vconcat) (or similar) before iterating.
  if (useContainerWidth && containerWidth && containerWidth > 0) {
    spec.width = containerWidth

    if ("vconcat" in spec) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO: Replace 'any' with a more specific type.
      spec.vconcat.forEach((child: any) => {
        // Skip non-object children (defensive check)
        if (child === null || typeof child !== "object") {
          return
        }
        // Skip setting width on children that are nested compositions
        // (hconcat, vconcat, concat, facet, repeat) as it causes
        // "infinite extent" errors.
        // Layer children should still receive width so layered + vconcat charts
        // can stretch consistently.
        // In valid Vega-Lite specs, composition operators are always top-level keys.
        if (
          "hconcat" in child ||
          "vconcat" in child ||
          "concat" in child ||
          "facet" in child ||
          "repeat" in child
        ) {
          return
        }
        child.width = containerWidth
      })
    }

lib/streamlit/elements/vega_charts.py:293

  • The _has_nested_composition docstring still states that only (hconcat, vconcat, concat, layer) are top-level composition keys, but the function now treats facet and repeat as compositions too. Please update that sentence/list so the documentation matches the actual detection logic.
    In valid Vega-Lite specs, composition operators (hconcat, vconcat, concat, layer)
    are always top-level keys of a view specification. They cannot be buried inside
    encoding, mark, or other nested properties. This allows us to check only the
    immediate children of vconcat for nested composition operators.

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

Consolidated Code Review

Summary

This PR fixes a rendering regression where Vega-Lite charts using vconcat with facet or repeat children would fail with "infinite extent" errors when width="stretch" or use_container_width=True. The root cause was that the nested composition detection logic only checked for hconcat, vconcat, concat, and layer operators but missed facet and repeat — both valid Vega-Lite multi-view composition operators.

The fix adds facet and repeat to the detection checks in three locations:

  1. Backend (vega_charts.py): _has_nested_composition() — determines autosize strategy (pad vs fit-x)
  2. Frontend (ArrowVegaLiteChart.tsx): hasNestedComposition() — determines whether to force stretch width
  3. Frontend (useVegaElementPreprocessor.ts): generateSpec() — skips setting explicit width on composition children

This now correctly covers all six Vega-Lite multi-view composition operators.

Code Quality

The changes are minimal, well-targeted, and consistent across all three code locations. The fix follows existing patterns perfectly. Both reviewers agreed on high code quality with no blocking issues.

Minor issues (both reviewers agreed):

  1. Docstring inconsistency in vega_charts.py (line 290): The second paragraph of the _has_nested_composition docstring still lists only (hconcat, vconcat, concat, layer) as composition operators, even though facet and repeat were added to the first paragraph (line 286) and to the actual check (line 313). This parenthetical should include all six operators.

  2. JSDoc inconsistency in ArrowVegaLiteChart.tsx (line 69): The hasNestedComposition JSDoc says "composition operators (hconcat, vconcat, concat, layer)" without mentioning facet and repeat.

Both are documentation-only nits and don't affect correctness.

Test Coverage

Both reviewers rated test coverage as strong. Tests span all three layers:

  • Frontend unit tests: Both ArrowVegaLiteChart.test.tsx and useVegaElementPreprocessor.test.ts add test cases for facet and repeat, following existing parameterized test patterns.
  • Python unit tests: vega_charts_test.py adds test_has_nested_composition_vconcat_with_facet and test_vconcat_with_faceted_children_with_use_container_width_true_gets_pad.
  • E2E test: test_vconcat_layered_facet_regression_renders verifies end-to-end rendering with a realistic chart that reproduces the reported issue.

One gap (both reviewers agreed):

The Python backend tests add a _has_nested_composition unit test for facet but not for repeat. The frontend tests cover both operators. Adding test_has_nested_composition_vconcat_with_repeat would make the Python test suite symmetric with the frontend. This is a minor gap since the logic is identical for both operators, but would improve test parity.

Backwards Compatibility

No backwards compatibility concerns. Both reviewers agreed. The change only broadens detection of composition operators that already triggered the pad autosize fallback. Charts that previously worked are unaffected; charts that previously failed to render (vconcat+facet, vconcat+repeat) will now render correctly.

Security & Risk

No security concerns. Both reviewers agreed. The changes are purely in rendering logic for chart specifications. Regression risk is low because:

  • The fix extends existing detection logic with two additional operator checks.
  • The fallback behavior (pad autosize) is already battle-tested for other composition operators.
  • The E2E test provides a concrete regression guard.

Accessibility

No accessibility impact. Both reviewers agreed. The changes affect Vega-Lite chart rendering logic (autosize and width configuration) and do not modify DOM structure, ARIA attributes, or keyboard interactions.

Reviewer Agreement

Both reviewers (gpt-5.3-codex-high and opus-4.6-thinking) were in full agreement on all points:

  • Both approved the PR
  • Both identified the same docstring inconsistency in vega_charts.py
  • Both noted the missing Python repeat test case
  • Both found no security, accessibility, or backwards compatibility concerns
  • Both considered all flagged issues non-blocking

opus-4.6-thinking additionally flagged the JSDoc inconsistency in ArrowVegaLiteChart.tsx, which is consistent with and complementary to the other reviewer's findings.

Recommendations

  1. Update the docstring in vega_charts.py line 290: Change (hconcat, vconcat, concat, layer) to (hconcat, vconcat, concat, layer, facet, repeat) to match the updated function behavior and first paragraph.
  2. Update the JSDoc in ArrowVegaLiteChart.tsx line 69: Change (hconcat, vconcat, concat, layer) to (hconcat, vconcat, concat, layer, facet, repeat) for consistency.
  3. Add a Python unit test for repeat: Add test_has_nested_composition_vconcat_with_repeat to match the frontend test coverage, ensuring both new operators are explicitly tested on the backend.

All three are minor and non-blocking.

Verdict

APPROVED: Clean, well-tested bugfix that correctly extends the Vega-Lite composition operator detection to include facet and repeat, resolving rendering failures for vconcat charts with faceted/repeated children. Both reviewers approved unanimously. The minor docstring inconsistencies and missing repeat Python test are non-blocking.


Consolidated review by opus-4.6-thinking. Individual reviews below.


📋 Review by `gpt-5.3-codex-high`

Summary

This PR fixes Vega-Lite rendering regressions for vconcat charts when children are multi-view compositions (facet / repeat) and charts are stretched to container width.
The fix consistently updates nested-composition detection in frontend and backend logic, adjusts child-width preprocessing behavior, and adds targeted regression tests in frontend unit tests, Python unit tests, and Playwright e2e.

Code Quality

The implementation is focused and consistent across layers, with clear intent and good alignment between frontend (ArrowVegaLiteChart / useVegaElementPreprocessor) and backend (_has_nested_composition, autosize selection in _prepare_vega_lite_spec).

No blocking code quality issues found.

Non-blocking observation:

  • lib/streamlit/elements/vega_charts.py (around line 290): the _has_nested_composition docstring sentence listing composition operators still names only hconcat, vconcat, concat, layer, while implementation now also includes facet and repeat.

Test Coverage

Coverage is strong overall for the regression path:

  • Frontend unit tests now validate facet and repeat handling in both nested-composition detection and vconcat child-width preprocessing:
    • frontend/lib/src/components/elements/ArrowVegaLiteChart/ArrowVegaLiteChart.test.tsx
    • frontend/lib/src/components/elements/ArrowVegaLiteChart/useVegaElementPreprocessor.test.ts
  • Backend unit tests validate nested composition detection for facet and autosize behavior for faceted vconcat children:
    • lib/tests/streamlit/elements/vega_charts_test.py
  • E2E adds a realistic regression scenario reproducing the prior failure mode and asserts visible rendered graphics:
    • e2e_playwright/st_altair_chart.py
    • e2e_playwright/st_altair_chart_test.py

Residual gap (non-blocking):

  • I do not see a backend unit/e2e assertion specifically exercising the repeat branch added in _has_nested_composition (lib/streamlit/elements/vega_charts.py, around line 313).

Backwards Compatibility

No breaking API changes were introduced.
Behavior changes are limited to autosize/width handling for a narrow class of nested vconcat specs that previously produced rendering failures, which is backward-compatible and user-positive.

Security & Risk

No security concerns identified.
Regression risk appears low: the logic is scoped to chart-spec preprocessing/autosize decision paths and is covered by targeted tests.

Accessibility

No new interactive UI patterns or semantic markup changes were introduced in frontend rendering components.
No accessibility regressions identified from this diff.

Recommendations

  1. Consider adding a backend test case for vconcat with repeat children (mirroring the new facet autosize test pattern in lib/tests/streamlit/elements/vega_charts_test.py) to fully lock in parity with the new backend detection branch.
  2. Consider updating the _has_nested_composition docstring operator list in lib/streamlit/elements/vega_charts.py to explicitly include facet and repeat for maintainability.

Verdict

APPROVED: The fix is well-scoped, coherent across frontend/backend, and adequately tested for the reported regression scenario.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR fixes a regression where Vega-Lite charts using vconcat with facet or repeat children would fail to render with "infinite extent" errors when width="stretch" or use_container_width=True. The root cause was that the nested composition detection logic only checked for hconcat, vconcat, concat, and layer operators but missed facet and repeat — both valid Vega-Lite multi-view composition operators.

The fix adds facet and repeat to the detection checks in three places:

  1. Backend (vega_charts.py): _has_nested_composition() — determines autosize strategy (pad vs fit-x)
  2. Frontend (ArrowVegaLiteChart.tsx): hasNestedComposition() — determines whether to force stretch width
  3. Frontend (useVegaElementPreprocessor.ts): generateSpec() — skips setting explicit width on composition children

This now covers all six Vega-Lite multi-view composition operators.

Code Quality

The changes are minimal, well-targeted, and consistent across all three code locations. The fix follows the existing patterns perfectly.

Minor issues:

  1. Docstring inconsistency in vega_charts.py (line 290): The second paragraph of the _has_nested_composition docstring still lists only (hconcat, vconcat, concat, layer) as composition operators, even though facet and repeat were added to the first paragraph (line 285-286) and to the actual check (line 313). This parenthetical should include all six operators for consistency.

  2. JSDoc inconsistency in ArrowVegaLiteChart.tsx (lines 69-70): Similarly, the hasNestedComposition JSDoc says "composition operators (hconcat, vconcat, concat, layer)" without mentioning facet and repeat.

Both are documentation-only nits and don't affect correctness.

Test Coverage

Test coverage is thorough and well-structured:

  • Frontend unit tests: Both ArrowVegaLiteChart.test.tsx and useVegaElementPreprocessor.test.ts add test cases for facet and repeat, following the existing parameterized test patterns.
  • Python unit tests: vega_charts_test.py adds test_has_nested_composition_vconcat_with_facet and test_vconcat_with_faceted_children_with_use_container_width_true_gets_pad.
  • E2E test: test_vconcat_layered_facet_regression_renders verifies end-to-end rendering with a realistic chart that reproduces the reported issue.

One gap:

  1. The Python backend tests add a _has_nested_composition unit test for facet but not for repeat. The frontend tests cover both. Adding test_has_nested_composition_vconcat_with_repeat would make the Python test suite symmetric with the frontend. Similarly, there's no Python integration test for vconcat with repeat children getting pad autosize (only facet). This is a minor gap since the logic is identical for both operators, but would improve test parity.

Backwards Compatibility

No backwards compatibility concerns. The change only broadens the detection of composition operators that already triggered the "pad" autosize fallback path. Charts that previously worked (simple vconcat, vconcat+layer, etc.) are unaffected. Charts that previously failed to render (vconcat+facet, vconcat+repeat) will now render correctly.

Security & Risk

No security concerns. The changes are purely in rendering logic for chart specifications. The risk of regression is low because:

  • The fix extends existing detection logic with two additional operator checks.
  • The fallback behavior (pad autosize) is already battle-tested for other composition operators.
  • The E2E test provides a concrete regression guard.

Accessibility

No accessibility impact. The changes affect Vega-Lite chart rendering logic (autosize and width configuration) and do not modify DOM structure, ARIA attributes, or keyboard interactions.

Recommendations

  1. Update the docstring in vega_charts.py line 290: Change (hconcat, vconcat, concat, layer) to (hconcat, vconcat, concat, layer, facet, repeat) to match the updated function behavior and first paragraph.

  2. Update the JSDoc in ArrowVegaLiteChart.tsx lines 69-70: Change (hconcat, vconcat, concat, layer) to (hconcat, vconcat, concat, layer, facet, repeat) for consistency.

  3. Add a Python unit test for repeat: Add test_has_nested_composition_vconcat_with_repeat to match the frontend test coverage, ensuring both new operators are explicitly tested on the backend.

All three are minor and non-blocking.

Verdict

APPROVED: Clean, well-tested bugfix that correctly extends the Vega-Lite composition operator detection to include facet and repeat, resolving rendering failures for vconcat charts with faceted/repeated children. The minor docstring inconsistencies and missing repeat Python test are non-blocking.


This is an automated AI review by opus-4.6-thinking.

Treat `facet` and `repeat` children under `vconcat` as nested compositions in
both backend autosize selection and frontend width preprocessing.

This prevents forced stretch sizing that can trigger Vega "Infinite extent"
errors and blank chart renders (issue #14050). Add regression coverage across
Python unit tests, frontend unit tests, and E2E altair chart tests.
@sfc-gh-bnisco sfc-gh-bnisco force-pushed the 02-22-fix_vega-lite_render_vconcat_charts_with_faceted_repeated_children branch from fcbc0d3 to bd1892e Compare February 22, 2026 23:19
@sfc-gh-bnisco sfc-gh-bnisco added the feature:st.vega_lite_chart Related to the `st.vega_lite_chart` element label Feb 22, 2026
@sfc-gh-bnisco sfc-gh-bnisco marked this pull request as ready for review February 22, 2026 23:57
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-bnisco sfc-gh-bnisco merged commit 2d15b31 into develop Feb 23, 2026
56 checks passed
@sfc-gh-bnisco sfc-gh-bnisco deleted the 02-22-fix_vega-lite_render_vconcat_charts_with_faceted_repeated_children branch February 23, 2026 16:48
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 feature:st.vega_lite_chart Related to the `st.vega_lite_chart` element impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vconcat with separate faceted charts does not render chart while repeat with faceted charts does work.

3 participants