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]

Reply via email to