Skip to content

fix(charts): add query_context validation to prevent incomplete metadata#36076

Open
ysinghc wants to merge 10 commits into
apache:masterfrom
ysinghc:fix/chart-validaion
Open

fix(charts): add query_context validation to prevent incomplete metadata#36076
ysinghc wants to merge 10 commits into
apache:masterfrom
ysinghc:fix/chart-validaion

Conversation

@ysinghc

@ysinghc ysinghc commented Nov 11, 2025

Copy link
Copy Markdown
Contributor

User description

SUMMARY

This PR adds comprehensive validation for the query_context field in both ChartPostSchema and ChartPutSchema to ensure that when provided, it contains the required metadata fields (datasource and queries) needed for chart data retrieval.

Changes:

  • Created a new validate_query_context_metadata() function in superset/utils/schema.py that validates the structure of query_context JSON
  • Updated ChartPostSchema to use the new validator (previously used generic validate_json)
  • Updated ChartPutSchema to add the new validator (previously had no validation)
  • Added comprehensive unit tests for the new validator in tests/unit_tests/utils/test_schema.py
  • Added integration tests in tests/unit_tests/charts/test_schemas.py to verify schema-level validation

Rationale:
Previously, the query_context field only validated that the value was valid JSON, but didn't ensure it contained the necessary structure for chart operations. This could lead to runtime errors when charts are rendered with incomplete query context data. The new validation ensures data integrity at the API level.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A - Backend validation change with no UI impact

TESTING INSTRUCTIONS

  1. Run the unit tests:

    pytest tests/unit_tests/utils/test_schema.py -v
    pytest tests/unit_tests/charts/test_schemas.py::test_chart_post_schema_query_context_validation -v
    pytest tests/unit_tests/charts/test_schemas.py::test_chart_put_schema_query_context_validation -v
  2. Manual API testing (optional):

    • Start Superset in development mode
    • Try to create a chart (POST /api/v1/chart/) with invalid query_context (missing datasource or queries)
    • Verify that the API returns a validation error
    • Try with valid query_context containing both fields - should succeed
    • Try with null query_context - should succeed (field is nullable)
  3. Verify pre-commit hooks pass:

    git add .
    pre-commit run

ADDITIONAL INFORMATION


CodeAnt-AI Description

Reject incomplete chart query context data

What Changed

  • Creating or updating a chart now rejects query_context values that are not valid JSON objects with both datasource and queries
  • Empty or unset query_context values are still allowed
  • Invalid JSON and missing required fields now return clear validation errors instead of failing later when charts are used
  • Added coverage for chart create/update validation and for the new query context checks

Impact

✅ Fewer chart save failures
✅ Clearer chart validation errors
✅ Fewer runtime errors from incomplete chart 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:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

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:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

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.

@bito-code-review

bito-code-review Bot commented Nov 11, 2025

Copy link
Copy Markdown
Contributor

Code Review Agent Run #50c92e

Actionable Suggestions - 0
Additional Suggestions - 10
  • tests/unit_tests/charts/test_schemas.py - 2
    • Docstring missing period at end · Line 161-161
      Docstring should end with a period. This issue also appears on line 246.
      Code suggestion
       @@ -161,1 +161,1 @@
      -    """Test that ChartPostSchema validates query_context contains required metadata"""
      +    """Test that ChartPostSchema validates query_context contains required metadata."""
    • Missing trailing comma in dictionary · Line 169-169
      Missing trailing comma in dictionary/list literals. This issue appears on lines 169, 192, 254, and 265.
      Code suggestion
       @@ -168,2 +168,2 @@
      -            "queries": [{"metrics": ["count"], "columns": []}],
      -        }
      +            "queries": [{"metrics": ["count"], "columns": []}],
      +        }
  • superset/utils/schema.py - 3
    • Docstring format and imperative mood · Line 57-57
      Docstring should start summary on first line and use imperative mood. Change `"Validator for query_context field"` to `"Validate query_context field"`.
      Code suggestion
       @@ -56,4 +56,3 @@
       def validate_query_context_metadata(value: bytes | bytearray | str | None) -> None:
      -    """
      -    Validator for query_context field to ensure it contains required metadata.
      +    """Validate query_context field to ensure it contains required metadata.
      
           Validates that the query_context JSON contains the required 'datasource' and
    • String literal in exception message · Line 72-72
      Exception message `"JSON not valid"` should be assigned to a variable first. This is part of multiple similar issues (lines 53, 72, 76) that should be addressed consistently.
      Code suggestion
       @@ -69,3 +69,4 @@
           try:
               parsed_data = json.loads(value)
           except json.JSONDecodeError as ex:
      -        raise ValidationError("JSON not valid") from ex
      +        error_msg = "JSON not valid"
      +        raise ValidationError(error_msg) from ex
    • String literal in exception message · Line 76-76
      Exception message `"Query context must be a valid JSON object"` should be assigned to a variable first. This is part of multiple similar issues that should be addressed consistently.
      Code suggestion
       @@ -74,2 +74,3 @@
           # Validate required fields exist in the query_context
           if not isinstance(parsed_data, dict):
      -        raise ValidationError("Query context must be a valid JSON object")
      +        error_msg = "Query context must be a valid JSON object"
      +        raise ValidationError(error_msg)
  • tests/unit_tests/utils/test_schema.py - 5
    • Missing module docstring at file start · Line 1-1
      Add a module-level docstring to describe the purpose of this test file. This improves code documentation and follows Python conventions.
      Code suggestion
       @@ -17,6 +17,9 @@
      -
      -import pytest
      +"""
      +Unit tests for superset.utils.schema module.
      +"""
      +
      +import pytest
    • Docstring should end with period punctuation · Line 30-30
      Multiple docstrings throughout the file are missing proper punctuation. Function docstrings should end with a period. This affects lines 30, 37, 44, 52, 58, 65, 73, 79, 91, 103, 111, 119, 131, 141, 152, 166, 178, 190, 202, 208, 215, 223, 231, 239, 270, 277, 284, 291, 298, 305, 312, and 321.
      Code suggestion
       @@ -29,2 +29,2 @@
      -def test_validate_json_valid() -> None:
      -    """Test validate_json with valid JSON string"""
      +def test_validate_json_valid() -> None:
      +    """Test validate_json with valid JSON string."""
    • Missing trailing comma in dictionary literal · Line 84-84
      Multiple dictionary literals are missing trailing commas. This affects lines 84, 96, 121, 159, 171, 183, 195, 259, and 263. Adding trailing commas improves code consistency and makes diffs cleaner.
      Code suggestion
       @@ -81,5 +81,5 @@
      -        {
      -            "datasource": {"type": "table", "id": 1},
      -            "queries": [{"metrics": ["count"], "columns": []}],
      -        }
      +        {
      +            "datasource": {"type": "table", "id": 1},
      +            "queries": [{"metrics": ["count"], "columns": []}],
      +        }
    • Boolean positional argument in function call · Line 232-232
      Boolean value `True` is passed as a positional argument to `json.dumps()`. Consider using a keyword argument for better readability.
      Code suggestion
       @@ -231,2 +231,2 @@
      -    """Test validate_query_context_metadata with boolean instead of JSON object"""
      -    bool_value = json.dumps(True)
      +    """Test validate_query_context_metadata with boolean instead of JSON object"""
      +    bool_value = json.dumps(obj=True)
    • Magic number used in comparison statement · Line 301-301
      Magic numbers `2` are used in comparisons on lines 301 and 317. Consider defining these as named constants for better code maintainability.
      Code suggestion
       @@ -298,4 +298,5 @@
      -def test_one_of_case_insensitive_non_string_valid() -> None:
      -    """Test OneOfCaseInsensitive validator with non-string valid value"""
      -    validator = OneOfCaseInsensitive([1, 2, 3])
      -    result = validator(2)
      +def test_one_of_case_insensitive_non_string_valid() -> None:
      +    """Test OneOfCaseInsensitive validator with non-string valid value"""
      +    VALID_NUMBER = 2
      +    validator = OneOfCaseInsensitive([1, VALID_NUMBER, 3])
      +    result = validator(VALID_NUMBER)
Review Details
  • Files reviewed - 4 · Commit Range: 287674d..287674d
    • superset/charts/schemas.py
    • superset/utils/schema.py
    • tests/unit_tests/charts/test_schemas.py
    • tests/unit_tests/utils/test_schema.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 Default Agent You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@dosubot dosubot Bot added the api Related to the REST API label Nov 11, 2025
@ysinghc ysinghc changed the title feat(schema): add validation for query_context metadata in ChartPostSchema and ChartPutSchema fix(charts): add query_context validation to prevent incomplete metadata Nov 11, 2025

@korbit-ai korbit-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review by Korbit AI

Korbit automatically attempts to detect when you fix issues in new commits.
Category Issue Status
Design Duplicate JSON validation logic ▹ view
Design Imperative field validation ▹ view
Functionality Falsy JSON strings incorrectly bypass validation ▹ view
Performance Inefficient field validation with list collection ▹ view
Files scanned
File Path Reviewed
superset/utils/schema.py
superset/charts/schemas.py

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

Comment thread superset/utils/schema.py Outdated
Comment thread superset/utils/schema.py Outdated
Comment thread superset/utils/schema.py Outdated
Comment thread superset/utils/schema.py Outdated
@codecov

codecov Bot commented Nov 11, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 20.00000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.12%. Comparing base (8229c01) to head (96af010).

Files with missing lines Patch % Lines
superset/utils/schema.py 20.00% 12 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #36076      +/-   ##
==========================================
- Coverage   64.70%   64.12%   -0.58%     
==========================================
  Files        2686     2686              
  Lines      148626   148606      -20     
  Branches    34298    34290       -8     
==========================================
- Hits        96164    95297     -867     
- Misses      50697    51544     +847     
  Partials     1765     1765              
Flag Coverage Δ
hive 39.17% <6.66%> (-0.01%) ⬇️
mysql 57.80% <20.00%> (-0.01%) ⬇️
postgres 57.87% <20.00%> (-0.01%) ⬇️
presto 40.71% <6.66%> (-0.01%) ⬇️
python 58.07% <20.00%> (-1.20%) ⬇️
sqlite 57.45% <20.00%> (-0.01%) ⬇️
unit ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot removed the api Related to the REST API label Nov 11, 2025
ysinghc

This comment was marked as duplicate.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds validation to the query_context field in chart schemas to ensure it contains required metadata (datasource and queries) when provided, preventing runtime errors from incomplete query context data.

  • Created a new validate_query_context_metadata() function that validates both JSON structure and required fields
  • Updated ChartPostSchema to use the new validator (replacing generic validate_json)
  • Updated ChartPutSchema to add the new validator (previously had no validation)
  • Added comprehensive unit and integration tests

Reviewed Changes

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

File Description
superset/utils/schema.py Adds validate_query_context_metadata() function to validate query_context JSON structure and required fields
superset/charts/schemas.py Updates ChartPostSchema and ChartPutSchema to use the new validator for query_context field
tests/unit_tests/utils/test_schema.py Adds comprehensive unit tests for the new validator covering valid/invalid cases, edge cases, and error messages
tests/unit_tests/charts/test_schemas.py Adds integration tests verifying schema-level validation for both POST and PUT operations

Comment thread superset/utils/schema.py Outdated
@ysinghc ysinghc marked this pull request as draft November 16, 2025 13:03
@ysinghc ysinghc marked this pull request as ready for review November 16, 2025 13:03
@dosubot dosubot Bot added the api Related to the REST API label Nov 16, 2025

@korbit-ai korbit-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I've completed my review and didn't find any issues.

Files scanned
File Path Reviewed
superset/utils/schema.py
superset/charts/schemas.py

Explore our documentation to understand the languages and file types we support and the files we ignore.

Check out our docs on how you can make Korbit work best for you and your team.

Loving Korbit!? Share us on LinkedIn Reddit and X

@rusackas

Copy link
Copy Markdown
Member

Running CI, but I think i defer to @betodealmeida here :D

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment thread superset/utils/schema.py
Comment thread tests/unit_tests/utils/test_schema.py Outdated
Comment thread tests/unit_tests/charts/test_schemas.py
Comment thread tests/unit_tests/charts/test_schemas.py
@codeant-ai-for-open-source

Copy link
Copy Markdown
Contributor

CodeAnt AI is reviewing your PR.

@github-actions github-actions Bot removed the api Related to the REST API label Dec 13, 2025
@codeant-ai-for-open-source codeant-ai-for-open-source Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Dec 13, 2025
Comment thread superset/utils/schema.py
Comment thread tests/unit_tests/charts/test_schemas.py Outdated
Comment thread tests/unit_tests/charts/test_schemas.py Outdated
@codeant-ai-for-open-source

Copy link
Copy Markdown
Contributor

CodeAnt AI finished reviewing your PR.

@codeant-ai-for-open-source

Copy link
Copy Markdown
Contributor

💡 Enhance Your PR Reviews

We noticed that 3 feature(s) are not configured for this repository. Enabling these features can help improve your code quality and workflow:

🚦 Quality Gates

Status: Quality Gates are not enabled at the organization level
Learn more about Quality Gates

🎫 Jira Ticket Compliance

Status: Jira credentials file not found. Please configure Jira integration in your settings
Learn more about Jira Integration

⚙️ Custom Rules

Status: No custom rules configured. Add rules via organization settings or .codeant/review.json in your repository
Learn more about Custom Rules


Want to enable these features? Contact your organization admin or check our documentation for setup instructions.

@codeant-ai-for-open-source

Copy link
Copy Markdown
Contributor

CodeAnt AI is running Incremental review

@ysinghc

ysinghc commented Mar 22, 2026

Copy link
Copy Markdown
Contributor Author

@betodealmeida @villebro @michael-s-molina Request for review

@codeant-ai-for-open-source codeant-ai-for-open-source Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Mar 22, 2026
@bito-code-review

bito-code-review Bot commented Mar 22, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #ee8dfe

Actionable Suggestions - 0
Review Details
  • Files reviewed - 4 · Commit Range: 287674d..774df59
    • superset/charts/schemas.py
    • superset/utils/schema.py
    • tests/unit_tests/charts/test_schemas.py
    • tests/unit_tests/utils/test_schema.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

AI Code Review powered by Bito Logo

@rusackas

Copy link
Copy Markdown
Member

Thanks for sticking with this @ysinghc! The gap is real... ChartPutSchema.query_context has zero validation on master, so tightening it makes sense.

What I'm chewing on: this rejects the bad query_context at save time, but doesn't get at why the frontend produces one missing datasource/queries in the first place. If that's a frontend bug in buildQueryContext running on partial form_data, then this flips the failure from "saves but errors later" into "won't save at all" until the generation side is fixed too. And the original report mentions native filters hitting this, which live in the dashboard's json_metadata rather than going through the chart API, so I don't think this PR catches that path.

@betodealmeida do you think save-time validation is the right layer here, or should we be fixing the generation side? You've got way more context on this corner than I do.

@rusackas

Copy link
Copy Markdown
Member

@ysinghc this needs as mentioned. I''ll see if I can tackle that part now to help keep the ball moving forward.

@rusackas rusackas force-pushed the fix/chart-validaion branch from 774df59 to 54f3f27 Compare June 24, 2026 01:16
Comment thread superset/utils/schema.py
Comment on lines +114 to +118
required_fields = {"datasource", "queries"}
missing_fields: set[str] = required_fields - parsed_data.keys()
if missing_fields:
fields_str = ", ".join(sorted(missing_fields))
raise ValidationError(f"Query context is missing required fields: {fields_str}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: The validation only checks that datasource and queries keys exist, but does not validate their value types/content, so payloads like {"datasource": null, "queries": null} pass and fail later when query context is built/executed. Add structural checks (e.g., datasource must be an object and queries must be a list, ideally non-empty) to enforce the contract at schema-validation time. [incomplete implementation]

Severity Level: Major ⚠️
- ❌ Saved charts can store unusable query_context payloads.
- ❌ Chart data API `/api/v1/chart/<id>/data` returns 400 on use.
- ⚠️ MCP `get_chart_data` tooling may silently fall back or fail.
Steps of Reproduction ✅
1. The `validate_query_context_metadata` function at `superset/utils/schema.py:89-118`
only verifies that the parsed JSON object is a dict and that its key set includes
`"datasource"` and `"queries"` via `required_fields = {"datasource", "queries"}` and
`missing_fields = required_fields - parsed_data.keys()`, without validating value types or
contents, as shown in lines 114-118.

2. This validator is applied to `query_context` in both `ChartPostSchema` and
`ChartPutSchema` at `superset/charts/schemas.py:32-36` and `95-99`, so a payload like
`{"datasource": null, "queries": null}` serialized as a JSON string will pass schema
validation and be persisted into `Slice.query_context` (see
`superset/models/slice.py:69-84` where `query_context = Column(utils.MediumText())`).

3. When chart data is later requested via `GET /api/v1/chart/<id>/data` in
`superset/charts/data/api.py:150-31`, the code does `json_body =
json.loads(chart.query_context)` and then calls `query_context =
self._create_query_context_from_form(json_body)` at line 217, where
`_create_query_context_from_form` delegates to
`ChartDataQueryContextSchema().load(form_data)` (see the analogous implementation in
`superset/tasks/async_queries.py:1-12`). That schema expects a structured `datasource`
object and a list of query dicts; with `datasource=None` and `queries=None`, it will raise
a `ValidationError`.

4. The `ValidationError` from `ChartDataQueryContextSchema` is caught in
`superset/charts/data/api.py:224-41` and converted into a 400 response, and similar
parsing/validation occurs in MCP chart tooling
(`superset/mcp_service/chart/tool/get_chart_data.py:450-485` and
`superset/mcp_service/chart/tool/get_chart_sql.py:170-209`), meaning charts saved with
such minimally valid-but-structurally-wrong `query_context` pass the current metadata
validator but subsequently fail whenever their data or SQL is requested, leaving persisted
but unusable chart configurations.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/schema.py
**Line:** 114:118
**Comment:**
	*Incomplete Implementation: The validation only checks that `datasource` and `queries` keys exist, but does not validate their value types/content, so payloads like `{"datasource": null, "queries": null}` pass and fail later when query context is built/executed. Add structural checks (e.g., `datasource` must be an object and `queries` must be a list, ideally non-empty) to enforce the contract at schema-validation time.

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
👍 | 👎

@bito-code-review

bito-code-review Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8c0fa2

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/charts/schemas.py - 1
    • Inconsistent validation across schemas · Line 254-254
      `ImportV1ChartSchema.query_context` at line 1739 still uses `validate_json` while `PostRestApiCompactSchema` and `PostRestApiSchema` now use stricter `validate_query_context_metadata` requiring `datasource` and `queries` fields. This inconsistency means chart imports bypass the structural validation applied to API-created charts.
Review Details
  • Files reviewed - 4 · Commit Range: 4ad0d95..54f3f27
    • superset/charts/schemas.py
    • superset/utils/schema.py
    • tests/unit_tests/charts/test_schemas.py
    • tests/unit_tests/utils/test_schema.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

AI Code Review powered by Bito Logo

Comment thread superset/utils/schema.py
Comment on lines +99 to +100
if value is None or value == "":
return # Allow None values and empty strings

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Treating an empty string as valid query_context bypasses the new metadata checks and still allows persisting blank payloads; those charts later fail data retrieval paths that expect saved query context JSON. Only None should bypass validation, while empty strings should be rejected as invalid input. [incomplete implementation]

Severity Level: Major ⚠️
❌ /api/v1/chart/<id>/data fails for blank query_context.
⚠️ MCP get_chart_data treats chart as missing query_context.
Steps of Reproduction ✅
1. Create a chart via the Charts REST API endpoint `POST /api/v1/chart/`, implemented by
`ChartRestApi` in `superset/charts/api.py` where `add_model_schema = ChartPostSchema()` is
defined at lines 36-37, using a request body that includes `"query_context": ""` (empty
string).

2. During request validation, `ChartPostSchema` in `superset/charts/schemas.py` (lines
52-56) maps the `query_context` field to `utils.validate_query_context_metadata`, which
executes `validate_query_context_metadata` in `superset/utils/schema.py` (definition at
lines 89-98).

3. Inside `validate_query_context_metadata`, the check at
`superset/utils/schema.py:99-100` (`if value is None or value == "": return`) treats the
empty string as valid, so no `ValidationError` is raised and the chart is persisted with
`Slice.query_context` (column defined at `superset/models/slice.py:84`) set to `""`
instead of `NULL`.

4. Later, when fetching chart data via `GET /api/v1/chart/<pk>/data` in
`superset/charts/data/api.py`, the handler at `superset/charts/data/api.py:160-167`
executes `json_body = json.loads(chart.query_context)` (line 162); for a blank string this
raises `json.JSONDecodeError`, is caught, sets `json_body = None`, and then returns HTTP
400 with message `"Chart has no query context saved. Please save the chart again."`,
meaning a chart that passed validation cannot be used until its query_context is fixed.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/schema.py
**Line:** 99:100
**Comment:**
	*Incomplete Implementation: Treating an empty string as valid `query_context` bypasses the new metadata checks and still allows persisting blank payloads; those charts later fail data retrieval paths that expect saved query context JSON. Only `None` should bypass validation, while empty strings should be rejected as invalid input.

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
👍 | 👎

Comment thread superset/utils/schema.py
validate_json(value)

# Parse and validate the structure
parsed_data = json.loads(value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add an explicit type annotation for this parsed JSON variable so the new validation logic keeps full type-hint coverage. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This is newly added Python code and the local variable can be annotated. It currently lacks an explicit type hint, so it matches the rule requiring type hints on relevant variables.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/schema.py
**Line:** 106:106
**Comment:**
	*Custom Rule: Add an explicit type annotation for this parsed JSON variable so the new validation logic keeps full type-hint coverage.

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
👍 | 👎

Comment thread superset/utils/schema.py
raise ValidationError(error_msg)

# When query_context is provided (not None), validate it has required fields
required_fields = {"datasource", "queries"}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add a concrete collection type annotation for this required-fields variable to satisfy the type-hint requirement on newly introduced relevant variables. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This newly introduced variable is a concrete collection that can be annotated, but no type hint is provided. That is a real violation of the type-hint rule for relevant variables.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/schema.py
**Line:** 114:114
**Comment:**
	*Custom Rule: Add a concrete collection type annotation for this required-fields variable to satisfy the type-hint requirement on newly introduced relevant variables.

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
👍 | 👎


def test_validate_json_valid() -> None:
"""Test validate_json with valid JSON string."""
valid_json = '{"key": "value", "number": 123}'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add an explicit type annotation for this local test input variable to comply with the type-hint requirement. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This is new Python code in a test file and the local variable is untyped even though it can be annotated; this matches the type-hint requirement for relevant variables.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_schema.py
**Line:** 33:33
**Comment:**
	*Custom Rule: Add an explicit type annotation for this local test input variable to comply with the type-hint requirement.

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
👍 | 👎


def test_validate_json_valid_bytes() -> None:
"""Test validate_json with valid JSON bytes."""
valid_json = b'{"key": "value", "number": 123}'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add an explicit bytes type annotation for this variable instead of leaving it untyped. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This added local variable is a bytes value and is left without a type annotation, which violates the rule requiring type hints for annotatable Python variables.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_schema.py
**Line:** 40:40
**Comment:**
	*Custom Rule: Add an explicit bytes type annotation for this variable instead of leaving it untyped.

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
👍 | 👎


def test_validate_json_not_json() -> None:
"""Test validate_json with non-JSON string."""
not_json = "this is not json"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add a concrete type annotation for this string variable to satisfy the rule requiring typed relevant variables. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The variable is a newly added local string in Python code and could be annotated; leaving it untyped matches the type-hint rule violation.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_schema.py
**Line:** 68:68
**Comment:**
	*Custom Rule: Add a concrete type annotation for this string variable to satisfy the rule requiring typed relevant variables.

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
👍 | 👎


def test_validate_query_context_metadata_missing_queries() -> None:
"""Test validate_query_context_metadata with missing queries field."""
missing_queries = json.dumps({"datasource": {"type": "table", "id": 1}})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add an explicit type annotation for this serialized query-context variable. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This local serialized JSON variable is untyped even though it can be annotated, so it falls under the rule requiring type hints for relevant variables.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_schema.py
**Line:** 134:134
**Comment:**
	*Custom Rule: Add an explicit type annotation for this serialized query-context variable.

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
👍 | 👎


def test_validate_query_context_metadata_number_value() -> None:
"""Test validate_query_context_metadata with number instead of JSON object."""
number_value = json.dumps(12345)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add an explicit type annotation for this variable holding serialized numeric JSON data. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This is another newly added untyped local variable in Python test code, and it can be annotated directly, so the type-hint rule applies.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/test_schema.py
**Line:** 226:226
**Comment:**
	*Custom Rule: Add an explicit type annotation for this variable holding serialized numeric JSON data.

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
👍 | 👎

Comment thread superset/utils/schema.py
Comment on lines +109 to +118
if not isinstance(parsed_data, dict):
error_msg = "Query context must be a valid JSON object"
raise ValidationError(error_msg)

# When query_context is provided (not None), validate it has required fields
required_fields = {"datasource", "queries"}
missing_fields: set[str] = required_fields - parsed_data.keys()
if missing_fields:
fields_str = ", ".join(sorted(missing_fields))
raise ValidationError(f"Query context is missing required fields: {fields_str}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: The new validator only checks that datasource and queries keys exist, but it does not validate their types/shape. This allows invalid payloads such as {"datasource": null, "queries": null} or {"datasource": {}, "queries": "bad"} to pass schema validation and later crash when chart code builds a query context (for example in Slice.get_query_context() / QueryContextFactory.create()). Add structural checks that datasource is a dict with required datasource attributes and queries is a list of query objects (and reject null/invalid types). [incomplete implementation]

Severity Level: Major ⚠️
- ❌ Chart cache warm-up fails for malformed query_context metadata.
- ❌ Annotation layers using chart query_context crash during execution.
- ⚠️ Dataset column discovery breaks when query_context.queries is invalid.
Steps of Reproduction ✅
1. Create or update a chart via Chart REST API (`ChartRestApi` in
`superset/charts/api.py:31-59`) using `POST /api/v1/chart/` or `PUT /api/v1/chart/<id>`,
including a `query_context` payload like `{"datasource": null, "queries": null}`
(syntactically valid JSON with required keys but null values).

2. The incoming payload is validated by `ChartPostSchema` or `ChartPutSchema` in
`superset/charts/schemas.py:225-285`, where the `query_context` field at lines 251-255 and
85-89 uses `validate=utils.validate_query_context_metadata`, which only checks that
`"datasource"` and `"queries"` keys exist and explicitly allows null values as shown by
tests `test_validate_query_context_metadata_null_datasource` and
`test_validate_query_context_metadata_null_queries` in
`superset/tests/unit_tests/utils/test_schema.py:179-199`.

3. Because `validate_query_context_metadata` in `superset/utils/schema.py:50-79` only
enforces key presence (lines 69-77 in the file, corresponding to PR lines 109-118) and
does not validate that `datasource` is a dict or `queries` is an iterable of dicts, the
malformed `query_context` string is accepted, and `CreateChartCommand` /
`UpdateChartCommand` in `superset/commands/chart/create.py:45-62` and
`superset/commands/chart/update.py:55-75` persist it into `Slice.query_context`
(SQLAlchemy column defined in `superset/models/slice.py:85-93`).

4. Later, when Superset executes features that rely on the saved `query_context`, such as
cache warm-up (`_warm_up_non_legacy_cache` in
`superset/commands/chart/warm_up_cache.py:11-27`), annotation query processing
(`superset/common/query_context_processor.py:14-37`), or column discovery in
`superset/connectors/sqla/models.py:15-36`, they all call `chart.get_query_context()` in
`superset/models/slice.py:19-28`, which does `json.loads(self.query_context)` and then
`self.get_query_context_factory().create(**{...})`. Inside `QueryContextFactory.create` in
`superset/common/query_context_factory.py:45-89`, the comprehension `for query_obj in
queries` at lines 77-88 attempts to iterate `queries=None` and raises a `TypeError:
'NoneType' object is not iterable`, causing these operations to fail at runtime for any
chart whose `query_context` has the malformed structure that current validation permits.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/schema.py
**Line:** 109:118
**Comment:**
	*Incomplete Implementation: The new validator only checks that `datasource` and `queries` keys exist, but it does not validate their types/shape. This allows invalid payloads such as `{"datasource": null, "queries": null}` or `{"datasource": {}, "queries": "bad"}` to pass schema validation and later crash when chart code builds a query context (for example in `Slice.get_query_context()` / `QueryContextFactory.create()`). Add structural checks that `datasource` is a dict with required datasource attributes and `queries` is a list of query objects (and reject null/invalid types).

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
👍 | 👎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"error": "Dataset schema is invalid, caused by: QueryContextFactory.create() missing 2 required keyword-only arguments: 'datasource' and 'queries'"

3 participants