codeant-ai-for-open-source[bot] commented on code in PR #40774:
URL: https://github.com/apache/superset/pull/40774#discussion_r3358144319


##########
superset/charts/data/dashboard_filter_context.py:
##########
@@ -78,13 +78,21 @@ def _is_filter_in_scope_for_chart(
     position_json: dict[str, Any],
 ) -> bool:
     """
-    Determines whether a native filter applies to a given chart. When
-    chartsInScope is present on the filter config, uses that directly.
-    Otherwise falls back to scope.rootPath and scope.excluded with
-    the dashboard layout.
+    Determines whether a native filter applies to a given chart.
+
+    When chartsInScope is present on the filter config, uses that directly.
+    Otherwise falls back to scope.rootPath and scope.excluded with the
+    dashboard layout. Also considers charts that were added to the dashboard
+    but were not instantiated in the layout.
     """
     if (charts_in_scope := filter_config.get("chartsInScope")) is not None:
-        return chart_id in charts_in_scope
+        if chart_id in charts_in_scope:
+            return True
+
+        # If the chart is found in position_json and not in chartsInScope,
+        # it was explicitly excluded by the filter scope config.
+        if _find_chart_layout_item(chart_id, position_json) is not None:
+            return False

Review Comment:
   **Suggestion:** The new fallback path calls `_find_chart_layout_item` before 
validating that `position_json` is a dictionary. If `dashboard.position_json` 
deserializes to a non-dict JSON type (for example `[]` from malformed/legacy 
data), `_find_chart_layout_item` will call `.values()` on that object and raise 
an `AttributeError`, breaking filter context resolution. Add a type guard 
(`isinstance(position_json, dict)`) before this lookup or normalize non-dict 
inputs to `{}`. [type error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ ChartData API 500 when dashboard layout JSON is list.
   - ⚠️ Affects dashboards with malformed or legacy position_json data.
   ```
   </details>
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Prepare a dashboard whose `position_json` column contains a non-dict JSON 
value, e.g.
   the literal string `"[]"`. This can be done by directly updating the
   `dashboards.position_json` field in the database or by importing legacy 
data. Other parts
   of the codebase (e.g. `superset/views/utils.py:366-371` and
   `superset/mcp_service/chart/chart_helpers.py:50-56`) explicitly guard
   `json.loads(dashboard.position_json)` with `isinstance(..., dict)`, 
indicating such
   malformed/legacy values are expected in practice.
   
   2. Call the Chart Data API endpoint for a chart on that dashboard: `GET
   /api/v1/chart/data/<chart_id>` with query parameter 
`filters_dashboard_id=<dashboard_id>`.
   This hits `superset/charts/data/api.py:183-196`, where 
`filters_dashboard_id` is parsed
   and `get_dashboard_filter_context` is invoked (lines 27-32 in the snippet, 
corresponding
   to `api.py:183-196`).
   
   3. Inside `get_dashboard_filter_context`
   (`superset/charts/data/dashboard_filter_context.py:35-67`), the code loads 
metadata and
   layout as:
   
      - `metadata = json.loads(dashboard.json_metadata or "{}")` (line 61)
   
      - `native_filter_config = metadata.get("native_filter_configuration", 
[])` (lines
      62-64)
   
      - `position_json: dict[str, Any] = json.loads(dashboard.position_json or 
"{}")` (line
      66)
   
      No `isinstance(position_json, dict)` check is performed here, so when
      `dashboard.position_json == "[]"`, `position_json` becomes a Python list.
   
   4. For each native filter, `_is_filter_in_scope_for_chart` is called with 
this list-valued
   `position_json` (`dashboard_filter_context.py:70-76`). Inside
   `_is_filter_in_scope_for_chart` (`lines 75-107`), when `chartsInScope` is 
present and the
   chart is not in it, or later when evaluating layout-based scope, the 
function calls
   `_find_chart_layout_item(chart_id, position_json)` at lines 94 and 104.
   `_find_chart_layout_item` (`lines 114-120`) immediately executes `for item in
   position_json.values():`, but since `position_json` is a list, this raises
   `AttributeError: 'list' object has no attribute 'values'`. This propagates 
up and causes
   the `/api/v1/chart/data` request with `filters_dashboard_id` to fail with a 
500 error,
   instead of gracefully treating the layout as empty. Adding an 
`isinstance(position_json,
   dict)` guard (or normalizing non-dict to `{}`) before these calls prevents 
the crash.
   ```
   </details>
   
   [Fix in 
Cursor](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=ed057894caaf47389c6be651378d4bec&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
 | [Fix in VSCode 
Claude](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=ed057894caaf47389c6be651378d4bec&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
   
   *(Use Cmd/Ctrl + Click for best experience)*
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** superset/charts/data/dashboard_filter_context.py
   **Line:** 94:95
   **Comment:**
        *Type Error: The new fallback path calls `_find_chart_layout_item` 
before validating that `position_json` is a dictionary. If 
`dashboard.position_json` deserializes to a non-dict JSON type (for example 
`[]` from malformed/legacy data), `_find_chart_layout_item` will call 
`.values()` on that object and raise an `AttributeError`, breaking filter 
context resolution. Add a type guard (`isinstance(position_json, dict)`) before 
this lookup or normalize non-dict inputs to `{}`.
   
   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.
   Once fix is implemented, also check other comments on the same PR, and ask 
user if the user wants to fix the rest of the comments as well. if said yes, 
then fetch all the comments validate the correctness and implement a minimal fix
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40774&comment_hash=d0814a5349f7cddf633acbd0ed01f040969f567ef679c2914dc6725dff1edf37&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F40774&comment_hash=d0814a5349f7cddf633acbd0ed01f040969f567ef679c2914dc6725dff1edf37&reaction=dislike'>👎</a>



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to