fix(AlertsReports): validate anchor_list is a list#38723
Conversation
Sequence DiagramThis PR adds a type check after parsing the dashboard anchor so only list values are treated as tab anchors. If the parsed anchor is not a list, execution now follows the existing fallback path and returns a single dashboard URL. sequenceDiagram
participant Scheduler
participant ReportExecutor
participant JsonParser
participant UrlBuilder
Scheduler->>ReportExecutor: Execute dashboard report
ReportExecutor->>JsonParser: Parse dashboard anchor JSON
alt Parsed value is a list
JsonParser-->>ReportExecutor: Return tab anchor list
ReportExecutor->>UrlBuilder: Build URLs for selected tabs
UrlBuilder-->>ReportExecutor: Return tab URLs
else Parsed value is not a list or invalid JSON
JsonParser-->>ReportExecutor: Return decode error
ReportExecutor->>UrlBuilder: Build single dashboard URL
UrlBuilder-->>ReportExecutor: Return single URL
end
ReportExecutor-->>Scheduler: Return dashboard URLs
Generated by CodeAnt AI |
| anchor_list = json.loads(anchor) | ||
| if not isinstance(anchor_list, list): | ||
| raise json.JSONDecodeError( | ||
| "Anchor value is not a list", anchor, 0 | ||
| ) |
There was a problem hiding this comment.
Suggestion: json.loads is called directly on anchor without checking its runtime type. If stored report metadata contains a non-string anchor (for example a legacy/prevalidated list), json.loads raises TypeError, which is not caught by the except json.JSONDecodeError block and can fail report execution instead of falling back safely. [type error]
Severity Level: Major ⚠️
- ❌ Dashboard report execution can crash on malformed anchor type.
- ❌ Scheduled report emails/screenshots may not be generated.
- ⚠️ Celery reports.execute task logs unexpected execution errors.| anchor_list = json.loads(anchor) | |
| if not isinstance(anchor_list, list): | |
| raise json.JSONDecodeError( | |
| "Anchor value is not a list", anchor, 0 | |
| ) | |
| if isinstance(anchor, list): | |
| anchor_list = anchor | |
| elif isinstance(anchor, str): | |
| anchor_list = json.loads(anchor) | |
| else: | |
| raise json.JSONDecodeError( | |
| "Anchor value is not a list", str(anchor), 0 | |
| ) | |
| if not isinstance(anchor_list, list): | |
| raise json.JSONDecodeError( | |
| "Anchor value is not a list", anchor, 0 | |
| ) |
Steps of Reproduction ✅
1. Update an existing report via `PUT /api/v1/report/<id>` (API class
`ReportScheduleRestApi` in `superset/reports/api.py:66`, using `ReportSchedulePutSchema`
at `superset/reports/api.py:194`), setting `extra.dashboard.anchor` to a JSON array/list
value instead of a string.
2. This payload is accepted because `extra` is an untyped dict (`fields.Dict`) in
`superset/reports/schemas.py:371`, and `UpdateReportScheduleCommand.validate()`
(`superset/commands/report/update.py:58`) does not call `_validate_report_extra` (only
create does in `superset/commands/report/create.py:143`).
3. When the schedule runs (`reports.execute` Celery task in
`superset/tasks/scheduler.py:116-134`), execution reaches dashboard screenshot generation,
which calls `get_dashboard_urls()` from `_get_screenshots()`
(`superset/commands/report/execute.py:385`).
4. In `get_dashboard_urls()` (`superset/commands/report/execute.py:271`),
`json.loads(anchor)` is called on a Python list, raising `TypeError`; the handler only
catches `json.JSONDecodeError` at `superset/commands/report/execute.py:282`, so execution
fails instead of graceful fallback.Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset/commands/report/execute.py
**Line:** 271:275
**Comment:**
*Type Error: `json.loads` is called directly on `anchor` without checking its runtime type. If stored report metadata contains a non-string `anchor` (for example a legacy/prevalidated list), `json.loads` raises `TypeError`, which is not caught by the `except json.JSONDecodeError` block and can fail report execution instead of falling back safely.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.There was a problem hiding this comment.
Code Review Agent Run #ee0d0e
Actionable Suggestions - 1
-
superset/commands/report/execute.py - 1
- Incomplete input validation · Line 271-275
Review Details
-
Files reviewed - 2 · Commit Range:
c31eb44..c31eb44- superset/commands/report/execute.py
- tests/unit_tests/commands/report/execute_test.py
-
Files skipped - 0
-
Tools
- Whispers (Secret Scanner) - ✔︎ Successful
- Detect-secrets (Secret Scanner) - ✔︎ Successful
- MyPy (Static Code Analysis) - ✔︎ Successful
- Astral Ruff (Static Code Analysis) - ✔︎ Successful
Bito Usage Guide
Commands
Type the following command in the pull request comment and save the comment.
-
/review- Manually triggers a full AI review. -
/pause- Pauses automatic reviews on this pull request. -
/resume- Resumes automatic reviews. -
/resolve- Marks all Bito-posted review comments as resolved. -
/abort- Cancels all in-progress reviews.
Refer to the documentation for additional commands.
Configuration
This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.
Documentation & Help
| anchor_list = json.loads(anchor) | ||
| if not isinstance(anchor_list, list): | ||
| raise json.JSONDecodeError( | ||
| "Anchor value is not a list", anchor, 0 | ||
| ) |
There was a problem hiding this comment.
The validation checks if anchor_list is a list but doesn't verify that all elements are strings, as expected by _get_tabs_urls(tab_anchors: list[str]). If the JSON contains a list of non-strings (e.g., integers), it will proceed and likely cause a runtime error later when creating permalinks. Consider adding a check for element types to match the intended list[str] type.
Code Review Run #ee0d0e
Should Bito avoid suggestions like this for future reviews? (Manage Rules)
- Yes, avoid them
(cherry picked from commit 100ad7d)
User description
SUMMARY
This pr fixes an edge case where anchor_link is not a list and split into individual characters. We now check for it and raise an error if so.
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
TESTING INSTRUCTIONS
ADDITIONAL INFORMATION
CodeAnt-AI Description
Fix dashboard report anchor handling to avoid iterating over non-list values
What Changed
Impact
✅ Fewer invalid dashboard tab URLs in alert/report exports✅ Clearer single-tab fallback when anchor value is malformed✅ Fewer broken alert report executions caused by malformed anchor data💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.