Repository navigation
fix(importers): catch YAMLError instead of narrower ParserError in load_yaml - #42426
Conversation
…ad_yaml load_yaml() only caught yaml.parser.ParserError, but yaml.safe_load can raise sibling exceptions under yaml.error.YAMLError (e.g. ScannerError, ComposerError) that are not subclasses of ParserError. These leaked past the except clause uncaught, through validate() in ImportModelsCommand and past the API layer's lack of a try/except around command.run(), resulting in an opaque 500 instead of the intended 422 ValidationError. Widen the catch to yaml.YAMLError, matching the existing import_tag() pattern in this same file.
Code Review Agent Run #df693aActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #42426 +/- ##
==========================================
- Coverage 65.24% 65.24% -0.01%
==========================================
Files 2795 2795
Lines 157643 157643
Branches 36061 36061
==========================================
- Hits 102853 102850 -3
- Misses 52814 52816 +2
- Partials 1976 1977 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…apache/superset#42426 First run of the daily superset-error-cleanup schedule: sibling-site-drift fix in superset/commands/importers/v1/utils.py, same bug class as #42366/#42401. Self-review clean, reviewer assigned by Minerva (notification pending green CI).
SUMMARY
load_yaml()insuperset/commands/importers/v1/utils.pyonly caughtyaml.parser.ParserError, missing sibling exceptions underyaml.error.YAMLError(ScannerError,ComposerError,ReaderError,ConstructorError). A raw error from these classes propagated as an unhandled 500 instead of the intendedValidationError→CommandInvalidError(422) with a clear "Not a valid YAML file" message. This mirrors the same bug class fixed in #42366 and #42401, and this file already has a sibling call site (import_tag()) that catches the broaderyaml.YAMLErrorcorrectly — this PR bringsload_yaml()in line with that existing pattern.PROBLEM
load_yaml()is used byload_metadata()andload_configs()to parse every YAML file in an import ZIP (databases, dashboards, charts, datasets, SSH tunnels). It only catchesyaml.parser.ParserError:But
yaml.parser.ParserError,yaml.scanner.ScannerError,yaml.composer.ComposerError, and others are siblings — all direct/indirect subclasses ofyaml.error.YAMLError, not of each other. For example,yaml.safe_load('key: "unterminated string')raisesyaml.scanner.ScannerError, which is not caught here.This is reachable end-to-end:
load_configs()runs insideImportModelsCommand.validate(), called fromrun()before the try/except that wraps_import(), so nothing in the command layer catches a leaked exception. The API layer (e.g.dashboards/api.pyimport_, and the chart/dataset/database equivalents) has no try/except aroundcommand.run()either — it relies only on Flask-AppBuilder's@safedecorator, which turns any uncaught exception into an opaque generic 500, discarding the actual reason. So importing a dashboard/chart/dataset/database ZIP with a YAML file that's malformed in a way other than aParserErrorcurrently surfaces as an opaque 500 instead of a proper validation error.FIX
Widen the
exceptclause inload_yaml()toexcept yaml.YAMLError as ex:, matching the already-correct sibling catch inimport_tag()in this same file. No other exception handling was touched; the deprecated v0 importer (superset/commands/dataset/importers/v0.py) has the same narrow-catch pattern but is out of scope for this PR.TESTING INSTRUCTIONS
TestLoadYamltotests/unit_tests/commands/importers/v1/utils_test.pywith two tests: one confirming the existingParserErrorpath still raisesValidationError, and one confirming aScannerError-triggering input ('key: "unterminated string') now also raisesValidationErrorinstead of leaking the rawyaml.scanner.ScannerError.git stashthat the newScannerErrortest fails on pre-fix code (yaml.scanner.ScannerErroruncaught) and passes after the fix.pytest tests/unit_tests/commands/importers/v1/utils_test.py— 8 passed, no regressions to the existingTestConvertTemporalColumnstests.ruff check,ruff format --check, andmypyon both changed files — no new issues.ADDITIONAL INFORMATION