getredash/redash · error · Exception

Failed to connect to Cloudflare D1: {str(e)}

Error message

Failed to connect to Cloudflare D1: {str(e)}

What it means

D1 runner's _query wraps requests exceptions from the Cloudflare D1 HTTP API call into 'Failed to connect to Cloudflare D1: <e>'. Connection-level problems (DNS, TLS, refused, HTTP errors) before any JSON parsing.

Source

Thrown at redash/query_runner/d1.py:85

        headers = {
            "Authorization": f"Bearer {self.configuration.get('cf_token')}",
            "Content-Type": "application/json",
        }
        body = {"sql": sql, "params": params or []}

        try:
            resp = session.post(self.configuration.get("cf_url"), headers=headers, data=json.dumps(body), timeout=30)
            resp.raise_for_status()
            data = resp.json()

            # Expected: { "result": [ { "results": [...] } ] }
            results = data.get("result", [])
            if not results:
                return []
            return results[0].get("results", [])

        except session.exceptions.RequestException as e:
            raise Exception(f"Failed to connect to Cloudflare D1: {str(e)}")
        except json.JSONDecodeError as e:
            raise Exception(f"Invalid JSON response from D1: {str(e)}")
        except KeyError as e:
            raise Exception(f"Unexpected response format from D1: {str(e)}")

    def run_query(self, query, user):
        try:
            rows = self._query(query)
            if not rows:
                return {"columns": [], "rows": []}, None

            # Infer columns from first row
            first_row = rows[0]
            columns = []
            for k, v in first_row.items():
                # Get the Python type name and map it to Redash type
                python_type = type(v).__name__
                redash_type = TYPES_MAP.get(python_type, TYPE_STRING)

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Verify account_id and database_id against the Cloudflare dashboard
  2. curl the API from the Redash host to confirm egress and IDs
  3. Fix proxy/TLS settings if curl also fails
  4. Regenerate the API token if the message includes an auth-related HTTP error

Example fix

# before
{"account_id": "wrong-id", "database_id": "db", "api_token": "..."}

# after
{"account_id": "a1b2c3...", "database_id": "<uuid from D1 dashboard>", "api_token": "..."}
Defensive patterns

Strategy: validation

Validate before calling

import requests
r = requests.get(f"https://api.cloudflare.com/client/v4/accounts/{account_id}", headers={"Authorization": f"Bearer {token}"}, timeout=5)
assert r.ok, 'fix account_id/token/network before querying'

Try / catch

try:
    rows = d1_runner._query(q)
except Exception as e:
    if str(e).startswith('Failed to connect to Cloudflare D1'):
        alert_network_or_ids(); rows = []

Prevention

When it happens

Trigger: POSTing to /client/v4/accounts/.../d1/database/.../query when requests raises RequestException: bad account/database IDs in the URL, blocked egress, or an invalid API endpoint.

Common situations: Wrong account_id or database_id in configuration, egress firewall blocking api.cloudflare.com, proxy/TLS interception, or a typo'd API base URL.

Related errors


AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28). Data as JSON: /api/errors/a152b62d5489bf70. Report an issue: GitHub.