Skip to content

fix(mcp): raise right error#39964

Merged
alexandrusoare merged 2 commits into
masterfrom
alexandrusoare/fix/corect-error-raising
May 20, 2026
Merged

fix(mcp): raise right error#39964
alexandrusoare merged 2 commits into
masterfrom
alexandrusoare/fix/corect-error-raising

Conversation

@alexandrusoare
Copy link
Copy Markdown
Contributor

@alexandrusoare alexandrusoare commented May 8, 2026

SUMMARY

Problem:
When a database is unreachable, MCP's generate_chart tells the user "Chart query failed to execute. The chart configuration is invalid" with suggestions like "Check that all columns exist." Users think their chart config is wrong when the real problem is the database is down.

Root cause:
Superset's query execution layer (helpers.py) already creates structured SupersetError objects with proper error types (e.g. CONNECTION_HOST_DOWN_ERROR) via db_engine_spec.extract_errors(). However, QueryCacheManager drops the structured errors list — only the raw error string survives. By the time _compile_chart() sees the error, it can't distinguish a connection failure from a config issue, so it always returns the same generic message.

Solution:
Propagate the structured errors through the pipeline (3 additive lines in core), then use them in _compile_chart() to return the correct error type.

  • QueryCacheManager: preserve query_result.errors alongside error_message
  • QueryContextProcessor: include errors in the payload dict
  • _compile_chart(): bypass ChartDataCommand (which raises and loses the structured errors) — run QueryContext.get_payload() directly and check query["errors"] for CONNECTION_* types
  • generate_chart.py: use compile_result.error_obj instead of hardcoding a generic error

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

TESTING INSTRUCTIONS

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@dosubot dosubot Bot added the change:backend Requires changing the backend label May 8, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented May 8, 2026

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 2c2aaa7
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/69fda1e2f189e500084d3830
😎 Deploy Preview https://deploy-preview-39964--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

SupersetErrorType.CONNECTION_DATABASE_PERMISSIONS_ERROR,
SupersetErrorType.CONNECTION_MISSING_PARAMETERS_ERROR,
SupersetErrorType.CONNECTION_DATABASE_TIMEOUT,
SupersetErrorType.GENERIC_DB_ENGINE_ERROR,
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: Including GENERIC_DB_ENGINE_ERROR in the connection-only allowlist causes _classify_as_database_error() to mark almost any compile failure as a database connectivity issue, because db_engine_spec.extract_errors() falls back to GENERIC_DB_ENGINE_ERROR for non-matching exceptions. This will misreport invalid SQL/chart config errors as "Unable to connect to the database." Remove this generic type from _CONNECTION_ERROR_TYPES (or add stricter checks on the extracted message/type) so only real connection/auth/network failures are classified as database connection errors. [incorrect condition logic]

Severity Level: Critical 🚨
- ❌ MCP generate_chart mislabels generic DB errors as connection failures.
- ⚠️ Preview-only compile checks report wrong root cause to users.
Steps of Reproduction ✅
1. Call the MCP `generate_chart` tool, implemented at
`superset/mcp_service/chart/tool/generate_chart.py:93-153`, with a `GenerateChartRequest`
whose config produces a query-time database error that is not a connection/auth/network
issue (for example, an invalid SQL expression in a virtual dataset or an incompatible
aggregate), so that the underlying query fails at runtime.

2. When `generate_chart` runs the compile check after creating or preparing the chart, it
calls `_compile_chart(form_data, dataset.id)` in the saved-chart path at
`generate_chart.py:120-126` or in the preview-only path at `generate_chart.py:239-246`,
which routes into `_compile_chart` in `superset/mcp_service/chart/compile.py:133-205`.

3. Inside `_compile_chart` (`compile.py:156-205`), the `ChartDataCommand.run()` call can
raise `ChartDataQueryFailedError` (as defined in
`superset/commands/chart/exceptions.py:138-143` and raised in
`superset/commands/chart/data/get_data_command.py:15-22`) when `payload["queries"]`
contains an `"error"` string from the database; this exception is caught in the `except
(ChartDataQueryFailedError, ChartDataCacheLoadError) as exc` block at
`compile.py:206-226`.

4. In that exception handler, `_classify_as_database_error(exc, dataset_id)` is invoked
(`compile.py:206-208`). `_classify_as_database_error` (`compile.py:66-95`) calls
`dataset.database.db_engine_spec.extract_errors(exc)` (`compile.py:84-87`), which uses the
engine spec implementation `BaseEngineSpec.extract_errors` at
`superset/db_engine_specs/base.py:31-41`. When the error message doesn't match any custom
regex in `custom_errors` or `CUSTOM_DATABASE_ERRORS`, `extract_errors` returns a single
`SupersetError` with `error_type=SupersetErrorType.GENERIC_DB_ENGINE_ERROR` as its
fallback (`base.py:35-41`). Because `_CONNECTION_ERROR_TYPES` in `compile.py:52-65`
explicitly includes `SupersetErrorType.GENERIC_DB_ENGINE_ERROR`, the `any(e.error_type in
_CONNECTION_ERROR_TYPES for e in errors)` check at `compile.py:86-87` evaluates to True
even for non-connection engine errors, causing `_classify_as_database_error` to return
True and `_compile_chart` to treat the failure as a database connection error, returning
`_build_database_error(...)` (`compile.py:207-219)`. This produces a
`ChartGenerationError` with `error_type="database_connection_error"` and message `"Unable
to connect to the database."` (`compile.py:98-110`), which is then surfaced back to
`generate_chart` where `compile_result.error_obj` is used as the error payload
(`generate_chart.py:143-158` and `generate_chart.py:15-31`), misleading users into
thinking the database is unreachable when the underlying issue was a generic engine/SQL
error.

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/mcp_service/chart/compile.py
**Line:** 64:64
**Comment:**
	*Incorrect Condition Logic: Including `GENERIC_DB_ENGINE_ERROR` in the connection-only allowlist causes `_classify_as_database_error()` to mark almost any compile failure as a database connectivity issue, because `db_engine_spec.extract_errors()` falls back to `GENERIC_DB_ENGINE_ERROR` for non-matching exceptions. This will misreport invalid SQL/chart config errors as "Unable to connect to the database." Remove this generic type from `_CONNECTION_ERROR_TYPES` (or add stricter checks on the extracted message/type) so only real connection/auth/network failures are classified as database connection errors.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We include GENERIC_DB_ENGINE_ERROR because many engines (BigQuery, Snowflake, Athena, Databricks, Trino) lack specific CONNECTION_* regex patterns — all their connection failures fall back to this type. Excluding it would mean connection errors on these databases still show as "chart configuration is invalid," defeating the purpose of this fix.

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.

Customized review instruction saved!

Instruction:

Keep SupersetErrorType.GENERIC_DB_ENGINE_ERROR in the connection-error allowlist for chart compilation so engines without specific CONNECTION_* patterns still surface real database connection failures correctly.

Applied to:

  • superset/mcp_service/chart/**

💡 To manage or update this instruction, visit: CodeAnt AI Settings

@bito-code-review
Copy link
Copy Markdown
Contributor

The flagged issue is correct: including GENERIC_DB_ENGINE_ERROR in _CONNECTION_ERROR_TYPES causes _classify_as_database_error to misclassify non-connection errors as database connectivity issues, since extract_errors falls back to it for unmatched exceptions. Removing GENERIC_DB_ENGINE_ERROR from the set improves accuracy by limiting connection error classification to specific types. Here's the updated code snippet for _CONNECTION_ERROR_TYPES:

superset/mcp_service/chart/compile.py

_CONNECTION_ERROR_TYPES = {
    SupersetErrorType.CONNECTION_INVALID_USERNAME_ERROR,
    SupersetErrorType.CONNECTION_INVALID_PASSWORD_ERROR,
    SupersetErrorType.CONNECTION_INVALID_HOSTNAME_ERROR,
    SupersetErrorType.CONNECTION_PORT_CLOSED_ERROR,
    SupersetErrorType.CONNECTION_INVALID_PORT_ERROR,
    SupersetErrorType.CONNECTION_HOST_DOWN_ERROR,
    SupersetErrorType.CONNECTION_ACCESS_DENIED_ERROR,
    SupersetErrorType.CONNECTION_UNKNOWN_DATABASE_ERROR,
    SupersetErrorType.CONNECTION_DATABASE_PERMISSIONS_ERROR,
    SupersetErrorType.CONNECTION_MISSING_PARAMETERS_ERROR,
    SupersetErrorType.CONNECTION_DATABASE_TIMEOUT,
}

@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

❌ Patch coverage is 17.85714% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.87%. Comparing base (5b5dd01) to head (5a019b3).
⚠️ Report is 93 commits behind head on master.

Files with missing lines Patch % Lines
superset/mcp_service/chart/compile.py 19.23% 21 Missing ⚠️
superset/mcp_service/chart/tool/generate_chart.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #39964      +/-   ##
==========================================
- Coverage   63.88%   63.87%   -0.02%     
==========================================
  Files        2583     2583              
  Lines      136604   136651      +47     
  Branches    31502    31508       +6     
==========================================
+ Hits        87276    87281       +5     
- Misses      47812    47854      +42     
  Partials     1516     1516              
Flag Coverage Δ
hive 39.36% <17.85%> (-0.03%) ⬇️
mysql 59.02% <17.85%> (-0.04%) ⬇️
postgres 59.10% <17.85%> (-0.04%) ⬇️
presto 41.06% <17.85%> (-0.03%) ⬇️
python 60.54% <17.85%> (-0.04%) ⬇️
sqlite 58.74% <17.85%> (-0.04%) ⬇️
unit 100.00% <ø> (ø)

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

☔ View full report in Codecov by Sentry.
📢 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.

Copy link
Copy Markdown
Contributor

@bito-code-review bito-code-review Bot left a comment

Choose a reason for hiding this comment

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

Code Review Agent Run #487b42

Actionable Suggestions - 1
  • superset/mcp_service/chart/compile.py - 1
Additional Suggestions - 3
  • superset/mcp_service/chart/compile.py - 3
    • Performance Regression · Line 341-346
      Adding a database query (DatasetDAO.find_by_id) in the error handling path of chart compilation may impact performance when errors occur, as the compile check is intended to be fast.
    • Code Duplication · Line 213-219
      The two except blocks return identical CompileResult for database errors. Consider extracting a helper function to avoid duplication.
    • Broad Exception Handling · Line 347-347
      The except Exception clause catches all exceptions, which may mask unexpected errors. Consider catching more specific exceptions or removing the broad catch if not necessary.
Review Details
  • Files reviewed - 3 · Commit Range: 2c2aaa7..2c2aaa7
    • superset/mcp_service/chart/compile.py
    • superset/mcp_service/chart/tool/generate_chart.py
    • tests/unit_tests/mcp_service/chart/test_compile.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

if dataset and dataset.database and isinstance(exc, Exception):
errors = dataset.database.db_engine_spec.extract_errors(exc)
return any(e.error_type in _CONNECTION_ERROR_TYPES for e in errors)
except Exception: # pylint: disable=broad-except
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.

Overly broad exception catch blocks

Line 347 catches bare Exception which is too broad. Catch specific exception types instead (e.g., AttributeError, KeyError, TypeError) to avoid masking unexpected errors.

Code suggestion
Check the AI-generated fix before applying
Suggested change
except Exception: # pylint: disable=broad-except
except (AttributeError, KeyError, TypeError):

Code Review Run #487b42


Should Bito avoid suggestions like this for future reviews? (Manage Rules)

  • Yes, avoid them

@bito-code-review
Copy link
Copy Markdown
Contributor

bito-code-review Bot commented May 8, 2026

Code Review Agent Run #46d5f4

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 2c2aaa7..5a019b3
    • superset/mcp_service/chart/compile.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

@msyavuz msyavuz added the hold:testing! On hold for testing label May 13, 2026
@alexandrusoare alexandrusoare merged commit 6e8b3bf into master May 20, 2026
66 of 67 checks passed
@alexandrusoare alexandrusoare deleted the alexandrusoare/fix/corect-error-raising branch May 20, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:backend Requires changing the backend hold:testing! On hold for testing size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants