hasura/graphql-engine · error · errors.Error

citus_run_sql api request failed %d

Error message

citus_run_sql api request failed %d

What it means

CitusRunSQL returns this error when the Hasura server answers the citus_run_sql metadata API call with a non-200 status and an empty response body. Since there is no body text to relay, only the numeric HTTP status is reported. The error carries errors.KindHasuraAPI, indicating the CLI's request was delivered but the server refused to execute the SQL via the Citus source.

Source

Thrown at cli/internal/hasura/sourceops/citus/run_sql.go:35

		Type: "citus_run_sql",
		Args: input,
	}

	b := new(bytes.Buffer)

	resp, err := d.send(body, b)
	if err != nil {
		return nil, errors.E(op, err)
	}

	if resp.StatusCode != http.StatusOK {
		if b.Len() > 0 {
			return nil, errors.E(op, errors.KindHasuraAPI, b.String())
		} else {
			return nil, errors.E(
				op,
				errors.KindHasuraAPI,
				fmt.Errorf("citus_run_sql api request failed %d", resp.StatusCode),
			)
		}
	}

	o := new(hasura.CitusRunSQLOutput)
	if err = json.NewDecoder(b).Decode(o); err != nil {
		return nil, errors.E(op, err)
	}

	return o, nil
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Decode the embedded HTTP status: 401/403 → verify admin secret; 404 → confirm citus source support; 5xx → check Hasura and Citus database logs
  2. Validate the Citus database connection directly (psql with the same URL) to rule out network/credential issues
  3. Run the CLI with --debug to see the raw HTTP exchange
  4. Ensure metadata for the citus source is consistent (POST /v1/metadata with export/inconsistent check)
  5. Align CLI and server versions

Example fix

// before
out, err := c.CitusRunSQL(args)
if err != nil { return err }

// after
out, err := c.CitusRunSQL(args)
if err != nil {
  if strings.Contains(err.Error(), "citus_run_sql api request failed") {
    return fmt.Errorf("citus_run_sql rejected; inspect server logs: %w", err)
  }
  return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Check source health before running migrations
// POST /v1/metadata {"type":"export_metadata"} → assert a kind:"citus" source with a reachable URL exists

Type guard

func isEmptyBodyAPIError(err error) bool {
  return err != nil && strings.Contains(err.Error(), "api request failed")
}

Try / catch

out, err := c.CitusRunSQL(args)
if err != nil {
  if isEmptyBodyAPIError(err) {
    return diagnoseFromStatus(err) // 401 vs 404 vs 5xx; then read server logs
  }
  return err
}

Prevention

When it happens

Trigger: Running 'hasura migrate apply' or another flow that calls citus_run_sql against a server that responds 401/403 (auth), 404 (citus source kind or endpoint missing), or 500 with empty body (target Citus/Postgres database unreachable, bad connection string, or metadata inconsistency).

Common situations: Citius source configured with an unreachable database URL, expired DB credentials, wrong admin secret, Hasura server version lacking the citus plugin, or an infrastructure layer (proxy, service mesh) that discards error bodies.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/7c1e0c72c929a163. Report an issue: GitHub.