MatthewCurlerTAC opened a new issue, #41862: URL: https://github.com/apache/superset/issues/41862
### Bug description When sending a chart as a csv, the task fails with an HTTP 500 error. This affects only the csv content type: the chart sends correctly as a png, pdf, and text. The chart is successfully exported to csv via the UI. The error occurs whether: - the task is scheduled as an alert or a report - With and without `RESULTS_BACKEND` configured The dataset in question is small (40 rows) and has no null values in any of the cells. To reproduce: 1. Click **Settings** > **Alerts & Reports** 2. Add new report: **+ Report** 3. Under "Report Contents": 1) Content type = Chart; 2) Content format = csv 4. Save and trigger report Similar bugs have been reported in the past: - https://github.com/apache/superset/issues/28595: resolved by the author, but the same behavior as I am experiencing was noted in [this comment](https://github.com/apache/superset/issues/28595#issuecomment-2163500008) and it is not clear that they have the same cause. - https://github.com/apache/superset/issues/36439 was an RLS issue - there is no RLS in my environment - https://github.com/apache/superset/issues/36682 was caused by a non-standard delimiter - I'm using ','/the default - https://github.com/apache/superset/issues/27499 was caused by NULLs in the dataset - there are no NULLs in this example. This same alert has runs successfully on Superset 5.0.0, with the caveat that have been some minor configuration changes (within `superset_config.py`), which I have attempted to reverse for troubleshooting. ### Screenshots/recordings _No response_ ### Superset version master / latest-dev ### Python version 3.10 ### Node version I don't know ### Browser Not applicable ### Additional context ### Logs ``` [2026-07-07 16:01:01,125: INFO/ForkPoolWorker-1] Task reports.scheduler[9ad6226a-57bc-4ceb-a130-4e8960871a1f] succeeded in 0.010887326207011938s: None [2026-07-07 16:01:40,807: INFO/MainProcess] Task reports.execute[b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5] received [2026-07-07 16:01:40,808: INFO/ForkPoolWorker-1] Executing alert/report, task id: b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5, scheduled_dttm: 2026-07-07T16:01:40.770552+00:00 [2026-07-07 16:01:40,809: INFO/ForkPoolWorker-1] session is validated: id 5, executionid: b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5 [2026-07-07 16:01:41,084: INFO/ForkPoolWorker-1] Query for b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5 took 232.88 ms [2026-07-07 16:01:41,888: ERROR/ForkPoolWorker-1] CSV generation failed after 0.78s - execution_id: b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5 Traceback (most recent call last): File "/app/superset/commands/report/execute.py", line 575, in _get_csv_data csv_data = get_chart_csv_data( File "/app/superset/utils/csv.py", line 104, in get_chart_csv_data response = opener.open(chart_url, timeout=timeout) File "/usr/local/lib/python3.10/urllib/request.py", line 525, in open response = meth(req, response) File "/usr/local/lib/python3.10/urllib/request.py", line 634, in http_response response = self.parent.error( File "/usr/local/lib/python3.10/urllib/request.py", line 563, in error return self._call_chain(*args) File "/usr/local/lib/python3.10/urllib/request.py", line 496, in _call_chain result = func(*args) File "/usr/local/lib/python3.10/urllib/request.py", line 643, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 500: INTERNAL SERVER ERROR [2026-07-07 16:01:41,912: INFO/ForkPoolWorker-1] header_data in notifications for alerts and reports {'notification_type': 'Alert', 'notification_source': <ReportSourceFormat.CHART: 'chart'>, 'notification_format': 'CSV', 'chart_id': 252, 'dashboard_id': None, 'owners': [xxx], 'slack_channels': [], 'execution_id': 'b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5'}, taskid, b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5 [2026-07-07 16:01:44,783: INFO/ForkPoolWorker-1] Report sent to email, task_id: None, notification content is None [2026-07-07 16:01:44,798: ERROR/ForkPoolWorker-1] A downstream exception occurred while generating a report: b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5. Failed generating csv HTTP Error 500: INTERNAL SERVER ERROR Traceback (most recent call last): File "/app/superset/commands/report/execute.py", line 575, in _get_csv_data csv_data = get_chart_csv_data( File "/app/superset/utils/csv.py", line 104, in get_chart_csv_data response = opener.open(chart_url, timeout=timeout) File "/usr/local/lib/python3.10/urllib/request.py", line 525, in open response = meth(req, response) File "/usr/local/lib/python3.10/urllib/request.py", line 634, in http_response response = self.parent.error( File "/usr/local/lib/python3.10/urllib/request.py", line 563, in error return self._call_chain(*args) File "/usr/local/lib/python3.10/urllib/request.py", line 496, in _call_chain result = func(*args) File "/usr/local/lib/python3.10/urllib/request.py", line 643, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 500: INTERNAL SERVER ERROR The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/app/superset/tasks/scheduler.py", line 135, in execute ).run() File "/app/superset/commands/report/execute.py", line 1255, in run ).run() File "/app/superset/utils/decorators.py", line 267, in wrapped return on_error(ex) File "/app/superset/utils/decorators.py", line 232, in on_error raise ex File "/app/superset/utils/decorators.py", line 260, in wrapped result = func(*args, **kwargs) File "/app/superset/commands/report/execute.py", line 1196, in run ).next() File "/app/superset/commands/report/execute.py", line 958, in next self.send() File "/app/superset/commands/report/execute.py", line 851, in send notification_content = self._get_notification_content() File "/app/superset/commands/report/execute.py", line 743, in _get_notification_content csv_data = self._get_csv_data() File "/app/superset/commands/report/execute.py", line 603, in _get_csv_data raise ReportScheduleCsvFailedError( superset.commands.report.exceptions.ReportScheduleCsvFailedError: Failed generating csv HTTP Error 500: INTERNAL SERVER ERROR [2026-07-07 16:01:44,804: INFO/ForkPoolWorker-1] Task reports.execute[b5a86a9d-b68c-4dc3-bee0-7ebac8f759b5] succeeded in 3.9957655393518507s: None [2026-07-07 16:02:00,060: INFO/MainProcess] Task reports.scheduler[194eb99f-04fa-47c0-8bc9-c7be6faa8594] received [2026-07-07 16:02:00,077: INFO/ForkPoolWorker-1] Task reports.scheduler[194eb99f-04fa-47c0-8bc9-c7be6faa8594] succeeded in 0.014652850106358528s: None [2026-07-07 16:03:00,053: INFO/MainProcess] Task reports.scheduler[9b02af77-1cc8-40d9-8109-91a67fe650f1] received [2026-07-07 16:03:00,069: INFO/ForkPoolWorker-1] Task reports.scheduler[9b02af77-1cc8-40d9-8109-91a67fe650f1] succeeded in 0.01434366311877966s: None ``` ### Configuration Only (potentially) relevant sections included. #### Failing (master) ```python SUPERSET_WEBSERVER_PROTOCOL = os.getenv("SUPERSET_WEBSERVER_PROTOCOL", "https") SUPERSET_WEBSERVER_ADDRESS = os.environ.get("SUPERSET_WEBSERVER_ADDRESS", "0.0.0.0") SUPERSET_WEBSERVER_PORT = os.environ.get("SUPERSET_WEBSERVER_PORT", "8088") SUPERSET_WEBSERVER_TIMEOUT = 300 SUPERSET_WEB_SUBDOMAIN = os.environ.get("SUPERSET_WEB_SUBDOMAIN") ENABLE_PROXY_FIX = True # --------------------------------------------------- # TALISMAN SETTINGS # --------------------------------------------------- TALISMAN_ENABLED = True TALISMAN_CONFIG = { "content_security_policy": { "base-uri": ["'self'"], "default-src": ["'self'"], "img-src": [ "'self'", "blob:", "data:", "https://apachesuperset.gateway.scarf.sh", "https://static.scarf.sh/", # "https://cdn.brandfolder.io", # Uncomment when SLACK_ENABLE_AVATARS is True # noqa: E501 "https://ows.terrestris.de", "https://cdn.document360.io", ], "worker-src": ["'self'", "blob:"], "connect-src": [ "'self'", "https://api.mapbox.com", "https://events.mapbox.com", "https://tile.openstreetmap.org", "https://tile.osm.ch", "https://basemaps.cartocdn.com", "https://*.basemaps.cartocdn.com", "https://tiles.openfreemap.org", "https://*.maptiler.com", "https://tiles.stadiamaps.com", "https://tiles.versatiles.org", "https://*.protomaps.com", "https://*.maplibre.org", ], "object-src": "'none'", "style-src": [ "'self'", "'unsafe-inline'", *[f"https://{d}" for d in THEME_FONT_URL_ALLOWED_DOMAINS], ], "font-src": [ "'self'", *[f"https://{d}" for d in THEME_FONT_URL_ALLOWED_DOMAINS], ], "script-src": ["'self'", "'strict-dynamic'"], }, "content_security_policy_nonce_in": ["script-src"], "force_https": False, # Must be False to allow Alerts/Reports to connect via http "session_cookie_secure": True, } REDIS_HOST = os.getenv("REDIS_HOST", "redis") REDIS_PORT = int(os.getenv("REDIS_PORT", "6379")) # --------------------------------------------------- # SESSION MANAGEMENT # --------------------------------------------------- SESSION_SERVER_SIDE = True SESSION_TYPE = 'redis' SESSION_REDIS = Redis( host=REDIS_HOST, port=REDIS_PORT, db=5, ) SESSION_USE_SIGNER = True PERMANENT_SESSION_LIFETIME = timedelta(hours=24) SESSION_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" RATELIMIT_STORAGE_URI = f"redis://{REDIS_HOST}:{REDIS_PORT}/6" # --------------------------------------------------- # CACHE SETTINGS # --------------------------------------------------- CACHE_CONFIG: CacheConfig = { "CACHE_TYPE": "RedisCache", "CACHE_DEFAULT_TIMEOUT": 43200, # 12 hours "CACHE_KEY_PREFIX": "superset_results_", "CACHE_REDIS_HOST": REDIS_HOST, "CACHE_REDIS_PORT": REDIS_PORT, "CACHE_REDIS_DB": 0, } DATA_CACHE_CONFIG = CACHE_CONFIG RESULTS_BACKEND = RedisCache( host = REDIS_HOST, port = REDIS_PORT, db = 4, default_timeout = 1800, key_prefix = "superset_results_" ) class CeleryConfig: broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/3" imports = ( "superset.sql_lab", "superset.tasks.scheduler", "superset.tasks.thumbnails", "superset.tasks.cache", ) result_backend = f"redis://{REDIS_HOST}:{REDIS_PORT}/8" worker_prefetch_multiplier = 1 task_acks_late = False beat_schedule = { "reports.scheduler": { "task": "reports.scheduler", "schedule": crontab(minute="*", hour="*"), }, "reports.prune_log": { "task": "reports.prune_log", "schedule": crontab(minute=10, hour=0), }, } CELERY_CONFIG = CeleryConfig # --------------------------------------------------- # FEATURE FLAGS # --------------------------------------------------- FEATURE_FLAGS = { "ALERT_REPORTS": True, "ALERT_REPORTS_FILTER": True, "ALERT_REPORT_TABS": True, "AUTH_ROLES_SYNC_AT_LOGIN": True, "DASHBOARD_RBAC": True, "ENABLE_TEMPLATE_PROCESSING": True, "PLAYWRIGHT_REPORTS_AND_THUMBNAILS": True, "RLS_IN_SQLLAB": True, "TAGGING_SYSTEM": True, } ALERT_REPORTS_NOTIFICATION_DRY_RUN = False ALERT_REPORTS_DEFAULT_RETENTION = 30 ALERT_MINIMUM_INTERVAL = int(timedelta(minutes=60).total_seconds()) REPORT_MINIMUM_INTERVAL = int(timedelta(minutes=60).total_seconds()) SCREENSHOT_PLAYWRIGHT_WAIT_EVENT = "domcontentloaded" SCREENSHOT_PLAYWRIGHT_DEFAULT_TIMEOUT = int(timedelta(seconds=120).total_seconds()*1000) WEBDRIVER_BASEURL = "http://superset_app:8088/" WEBDRIVER_BASEURL_USER_FRIENDLY = f"https://{SUPERSET_WEB_SUBDOMAIN}.example.com" WEBDRIVER_OPTION_ARGS = ["--headless", "--marionette"] ``` #### Working (5.0.0) ```python DEV_MODE = False SECRET_KEY = os.getenv("SUPERSET_SECRET_KEY") SUPERSET_WEBSERVER_PROTOCOL = os.getenv("SUPERSET_WEBSERVER_PROTOCOL", "https") SUPERSET_WEBSERVER_ADDRESS = os.environ.get("SUPERSET_WEBSERVER_ADDRESS", "0.0.0.0") # noqa: S104 SUPERSET_WEBSERVER_PORT = os.environ.get("SUPERSET_WEBSERVER_PORT", "8088") SUPERSET_WEBSERVER_TIMEOUT = 300 # 5 minutes timeout for HTTP requests SUPERSET_WEB_SUBDOMAIN = os.environ.get("SUPERSET_WEB_SUBDOMAIN") WEBDRIVER_BASEURL = "http://superset:8088/" WEBDRIVER_BASEURL_USER_FRIENDLY = f"https://{SUPERSET_WEB_SUBDOMAIN}.example.com" # Will be behind reverse proxy ENABLE_PROXY_FIX = True # --------------------------------------------------- # CACHE SETTINGS # --------------------------------------------------- # RESULTS_BACKEND = FileSystemCache("/app/superset_home/sqllab") RESULTS_BACKEND = RedisCache( host=REDIS_HOST, port=REDIS_PORT, key_prefix="superset_results" ) RATELIMIT_STORAGE_URI = f"redis://{REDIS_HOST}:{REDIS_PORT}" CACHE_CONFIG = { "CACHE_TYPE": "RedisCache", "CACHE_DEFAULT_TIMEOUT": 300, "CACHE_KEY_PREFIX": "superset_", "CACHE_REDIS_HOST": REDIS_HOST, "CACHE_REDIS_PORT": REDIS_PORT, "CACHE_REDIS_DB": REDIS_RESULTS_DB, } DATA_CACHE_CONFIG = CACHE_CONFIG class CeleryConfig: broker_url = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}" imports = ( "superset.sql_lab", "superset.tasks.scheduler", "superset.tasks.thumbnails", "superset.tasks.cache", ) result_backend = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_RESULTS_DB}" worker_prefetch_multiplier = 1 task_acks_late = False beat_schedule = { "reports.scheduler": { "task": "reports.scheduler", "schedule": crontab(minute="*", hour="*"), }, "reports.prune_log": { "task": "reports.prune_log", "schedule": crontab(minute=10, hour=0), }, } CELERY_CONFIG = CeleryConfig # --------------------------------------------------- # FEATURE FLAGS # --------------------------------------------------- FEATURE_FLAGS = { "ALERT_REPORTS": True, "ALERT_REPORT_TABS": True, "ENABLE_TEMPLATE_PROCESSING": True, "TAGGING_SYSTEM": True, "DASHBOARD_RBAC": True, "PLAYWRIGHT_REPORTS_AND_THUMBNAILS": True, "RLS_IN_SQLLAB": True, "AUTH_ROLES_SYNC_AT_LOGIN": True } ``` ### Checklist - [x] I have searched Superset docs and Slack and didn't find a solution to my problem. - [x] I have searched the GitHub issue tracker and didn't find a similar bug report. - [x] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
