{"record":{"id":"eeef8f259a3f4308","repo":"apache/superset","slug":"str-ex","errorCode":null,"errorMessage":"str(ex)","messagePattern":"str\\(ex\\)","errorType":"exception","errorClass":"DatabaseUploadFailed","httpStatus":422,"severity":"error","filePath":"superset/commands/database/uploaders/columnar_reader.py","lineNumber":99,"sourceCode":"\n        :param file: The file to yield files from.\n        :return: A generator that yields files.\n        \"\"\"\n        file_suffix = Path(file.filename).suffix\n        if not file_suffix:\n            raise DatabaseUploadFailed(_(\"Unexpected no file extension found\"))\n        file_suffix = file_suffix[1:]  # remove the dot\n        if file_suffix == \"zip\":\n            if not is_zipfile(file):\n                raise DatabaseUploadFailed(_(\"Not a valid ZIP file\"))\n            try:\n                with ZipFile(file) as zip_file:\n                    # guard against decompression bombs before reading entries,\n                    # mirroring the importer path\n                    try:\n                        check_is_safe_zip(zip_file)\n                    except SupersetException as ex:\n                        raise DatabaseUploadFailed(str(ex)) from ex\n                    # check if all file types are of the same extension\n                    file_suffixes = {Path(name).suffix for name in zip_file.namelist()}\n                    if len(file_suffixes) > 1:\n                        raise DatabaseUploadFailed(\n                            _(\"ZIP file contains multiple file types\")\n                        )\n                    for filename in zip_file.namelist():\n                        with zip_file.open(filename) as file_in_zip:\n                            yield BytesIO(file_in_zip.read())\n            except BadZipfile as ex:\n                raise DatabaseUploadFailed(_(\"Not a valid ZIP file\")) from ex\n        else:\n            yield file\n\n    def file_to_dataframe(self, file: FileStorage) -> pd.DataFrame:\n        \"\"\"\n        Read Columnar file into a DataFrame\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/commands/database/uploaders/columnar_reader.py#L81-L117","documentation":"DatabaseUploadFailed whose message is the raw string of a SupersetException raised by superset.utils.zip.check_is_safe_zip inside ColumnarReader._yield_files. This is the decompression-bomb guard: before reading any entry, Superset checks the ZIP's declared total uncompressed size and file count against configured limits, and rejects oversized or entry-count-excessive archives. The user-visible message is whatever the guard reported (e.g. archive exceeds maximum allowed size).","triggerScenarios":"Uploading a .zip whose entries declare a combined uncompressed size above the configured limit (ZIP_BOMB_UNCOMPRESSED_SIZE_LIMIT style config) or with more entries than allowed; small compressed files that expand to very large Parquet buffers trigger it even when the .zip itself is small.","commonSituations":"Legitimately large data exports zipped for transfer; archives produced by tools that store files uncompressed but pad sizes; malicious or corrupted central-directory size fields; changing Superset config to lower limits.","solutions":["Re-package the data as a single uncompressed .parquet upload (skip the ZIP) or split it into smaller archives below the limit","Check the server's zip safety limits configuration and confirm the archive's declared uncompressed sizes (unzip -l) fall under them","Regenerate the ZIP with a standard tool to fix bogus size metadata","If the limit is intentionally too low for your workload, raise it in superset_config.py after reviewing memory capacity"],"exampleFix":"# inspect declared uncompressed sizes\nunzip -l data.zip   # compare 'uncompressed' column vs configured limit\n# split if too large\nzip data_part1.zip data_0.parquet; zip data_part2.zip data_1.parquet","handlingStrategy":"validation","validationCode":"import zipfile\n\ndef zip_within_limits(fh, max_uncompressed: int, max_entries: int) -> bool:\n    fh.seek(0)\n    with zipfile.ZipFile(fh) as z:\n        total = sum(i.file_size for i in z.infolist())\n        return len(z.namelist()) <= max_entries and total <= max_uncompressed","typeGuard":null,"tryCatchPattern":"try:\n    reader.file_to_dataframe(file)\nexcept DatabaseUploadFailed as ex:\n    if 'size' in str(ex).lower() or 'entries' in str(ex).lower():\n        # zip safety guard: split archive and retry with smaller parts\n        ...","preventionTips":["Zip only the parquet payload, no metadata entries","Keep declared uncompressed total under the server's zip limits","Split large exports into multiple archives"],"tags":["zip","zip-bomb","security","file-upload","limits"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}