Fix grid view crash when task converted to TaskGroup (#61208) #61279
+266
−5
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.
Description
This PR fixes issue #61208 where the grid view endpoint crashes with a 500 Internal Server Error when a task is converted to a TaskGroup (or vice versa) between DAG versions while historical DagRuns still exist.
Root Cause
The crash occurs in the _merge_node_dicts function within the FastAPI service layer. When a DAG structure evolves:
Historical Runs: May have a node (Task) with children=None.
Current Run: May have a node (TaskGroup) with the same ID but children=[...].
The recursive merge logic attempted to iterate over the None value from the historical run, leading to:
TypeError: 'NoneType' object is not iterable.
Changes Made
Defensive Recursion: Updated _merge_node_dicts in airflow/api_fastapi/core_api/services/ui/grid.py to handle None values by defaulting to an empty list during iteration and recursive calls.
Structural Flexibility: Enabled the grid view to gracefully handle ID collisions where a node's type changes across the DAG's lifecycle.
Testing:
Added 8 unit tests in tests/api_fastapi/core_api/services/ui/test_grid.py to validate recursive merging with mismatched types.
Added a regression integration test using the minimal DAG provided in the issue to ensure the 500 error is resolved.
Impact
Resolves the UI crash for users refactoring DAGs into TaskGroups.
Maintains backward compatibility for displaying historical runs with deprecated structures.
Checklist
[x] Code changes are covered with tests
[x] New unit test file created for service layer testing
[x] Integration test added to existing test suite
[x] Code follows existing patterns and conventions
[x] Passes all linting checks (ruff, pylint)
[x] No breaking changes
Generated-by: GitHub Copilot
Closes: #61208