Skip to content

fix(core): stop discarding API errors that quote an HTML tag - #42489

Open
gaurav0107 wants to merge 1 commit into
apache:masterfrom
gaurav0107:fix/33500-error-message-html-detection
Open

fix(core): stop discarding API errors that quote an HTML tag#42489
gaurav0107 wants to merge 1 commit into
apache:masterfrom
gaurav0107:fix/33500-error-message-html-detection

Conversation

@gaurav0107

Copy link
Copy Markdown
Contributor

SUMMARY

Fixes #33500.

When an API error message happens to contain an HTML tag, the UI throws the
whole message away and shows a generic Unexpected error Bad request. The
reproduction in the issue is a custom metric containing <a>: the database
rejects it, /api/v1/chart/data returns the full syntax error in message,
and the user sees nothing useful.

Root cause is in checkForHtml():

export function checkForHtml(str: string): boolean {
  return !isJsonString(str) && isProbablyHTML(str);
}

isProbablyHTML() answers "does this string contain a known HTML tag
anywhere?"
. That is the right question for the rendering helpers it was
written for (safeHtmlSpan, sanitizeHtmlIfNeeded, used on table cell
values), but the wrong one on the error path, which needs "is this an HTML
error page rather than prose?"
. A driver message that quotes <a>
mid-sentence trips the tag scan, so parseErrorJson() hands it to
retrieveErrorMessage(), which prefers the HTTP status and returns
Bad request.

The fix requires the string to begin with markup before it can be treated as
an error page. A page served by a proxy or gateway starts with
<!doctype html> or a tag; a server-authored message starts with prose. This
preserves the behaviour #29321 added — raw gateway HTML is still collapsed
into a status-code message — while letting real diagnostics through.

The guard goes in checkForHtml() rather than at either call site, so both
consumers (parseStringResponse() and parseErrorJson(), and therefore both
the string, JSON and text-fallback branches of getClientErrorObject()) are
covered by one change. The shared isProbablyHTML() in utils/html.tsx is
deliberately left alone.

No new sanitisation is needed: the resulting string is rendered as a React
text child (BasicErrorAlert renders <p>{body}</p>), and there is no
dangerouslySetInnerHTML anywhere on the error path.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

No visual change beyond the error text itself. For the message in the issue:

BeforeUnexpected error / Bad request
AfterUnexpected error / Error: HTTPDriver ... DB::Exception: Syntax error: failed at position 37 ('<') (line 1, col 37): <a> AS ...

TESTING INSTRUCTIONS

Automated:

cd superset-frontend
npx cross-env NODE_ENV=test npx jest \
  packages/superset-ui-core/test/query \
  packages/superset-ui-core/src/utils/html.test.tsx \
  src/middleware/asyncEvent.test.ts

The new test parseErrorJson keeps a server message that only quotes an HTML tag fails on master with error: "Bad request" and passes with this
change. The four pre-existing HTML tests in that file are the regression
guard for #29321 and stay green — their fixtures (<div>...,
<!doctype html>...) all start with markup. asyncEvent.test.ts covers the
one caller of parseErrorJson() outside this module.

Manual:

  1. Create a chart against any database whose driver echoes the failing
    expression back (ClickHouse in the issue report).
  2. Add a custom metric whose expression contains <a>.
  3. Press UPDATE CHART.
  4. The actual database error is shown instead of Bad request.

ADDITIONAL INFORMATION

@gaurav0107
gaurav0107 force-pushed the fix/33500-error-message-html-detection branch from b0fa8d7 to 8275e97 Compare July 27, 2026 21:31
@pull-request-size pull-request-size Bot added size/M and removed size/S labels Jul 27, 2026
@gaurav0107
gaurav0107 marked this pull request as ready for review July 27, 2026 21:42
@dosubot dosubot Bot added the change:frontend Requires changing the frontend label Jul 27, 2026
@gaurav0107
gaurav0107 force-pushed the fix/33500-error-message-html-detection branch from 8275e97 to 33a7bd5 Compare July 27, 2026 21:43
checkForHtml() asked "does this string contain a known HTML tag?", which is
the right question for rendering decisions but the wrong one on the error
path. A database driver that echoes the offending fragment back in its
syntax error -- for instance ClickHouse reporting a bad metric expression
containing <a> -- tripped the tag scan, so parseErrorJson() handed the
message to retrieveErrorMessage(), which prefers the HTTP status and
returned "Bad request". The real diagnostic was thrown away even though the
API had returned it in full.

Require the string to begin with markup before treating it as an HTML error
page. A page served by a proxy or gateway starts with <!doctype html> or a
tag; a server-authored message starts with prose. Both callers of
checkForHtml() -- parseStringResponse() and parseErrorJson() -- are fixed by
the single guard, and the shared isProbablyHTML() helper is untouched so
cell-value rendering keeps its existing semantics.

Fixes apache#33500
@gaurav0107
gaurav0107 force-pushed the fix/33500-error-message-html-detection branch from 33a7bd5 to 39a84f5 Compare July 27, 2026 22:29
@gaurav0107

Copy link
Copy Markdown
Contributor Author

Heads up on CI, since this branch has stale queued runs on three earlier SHAs.

The workflow concurrency group is keyed on PR number rather than head SHA with cancel-in-progress: true, so approving runs for more than one SHA makes them cancel each other. That is what left unit-tests-required, test-postgres-required, cypress-matrix-required and playwright-tests-required red a moment ago — the same trap the header comment in pr-lint.yml describes. Approving only the runs on head 39a84f5 should avoid it.

For reference, Frontend Build CI did complete green on 8275e97: all 8 sharded-jest-tests shards, plus lint-frontend, validate-frontend, test-storybook and report-coverage. The only change since then is reordering one conjunct inside checkForHtml so a non-string message keeps its existing isJsonString short-circuit.

@netlify

netlify Bot commented Jul 27, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 39a84f5
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a67dbd6bb75c200096b8998
😎 Deploy Preview https://deploy-preview-42489--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.

@bito-code-review

bito-code-review Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #fa78eb

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 39a84f5..39a84f5
    • superset-frontend/packages/superset-ui-core/src/query/getClientErrorObject.ts
    • superset-frontend/packages/superset-ui-core/test/query/getClientErrorObject.test.ts
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • Eslint (Linter) - ✔︎ 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

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Translation Regression Detected

A source change in this PR renamed or reworded strings, invalidating existing translations (they are now #, fuzzy) in fr. Please resolve the affected .po files before merging.

Note: neither intentionally deleting a translatable string nor filling a previously-untranslated entry with a fuzzy guess (e.g. an AI backfill) is a regression — only a confirmed translation that a renamed/reworded source string turned fuzzy is flagged here.

Language Invalidated translations
fr 493

How to fix

1. Install dependencies (if not already set up):

pip install -r superset/translations/requirements.txt
sudo apt-get install gettext   # or: brew install gettext

2. Re-extract strings and sync .po files:

./scripts/translations/babel_update.sh

This rewrites superset/translations/messages.pot from the current source files and merges the changes into every .po file. Strings whose msgid changed will be marked #, fuzzy.

3. Resolve the fuzzy entries in the affected language files (fr):

grep -n '#, fuzzy' superset/translations/<lang>/LC_MESSAGES/messages.po

For each fuzzy entry, either rewrite the msgstr to match the new string and remove the #, fuzzy line, or clear the msgstr to "" if you cannot provide a translation.

4. Commit your changes to the .po files.

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.26%. Comparing base (a44afd8) to head (39a84f5).
⚠️ Report is 38 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #42489   +/-   ##
=======================================
  Coverage   65.26%   65.26%           
=======================================
  Files        2794     2794           
  Lines      157615   157616    +1     
  Branches    36045    36045           
=======================================
+ Hits       102868   102869    +1     
  Misses      52769    52769           
  Partials     1978     1978           
Flag Coverage Δ
javascript 71.36% <100.00%> (+<0.01%) ⬆️

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.

@rusackas
rusackas requested a review from sadpandajoe July 29, 2026 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:frontend Requires changing the frontend packages size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bad request instead of an actual error if error message contains html tags

1 participant