gofr-dev/gofr · critical

%w: executing bulk: %w

Error message

%w: executing bulk: %w

What it means

Bulk() sends the prepared esapi.BulkRequest via req.Do(tracedCtx, c.client). If the transport-level request fails — network failure, connection refused, timeout, TLS error, or client not initialized — the method returns fmt.Errorf("%w: executing bulk: %w", errOperation, err), wrapping the errOperation sentinel plus a contextual "executing bulk" message and the underlying error. No response was received, so this is always a request-execution problem, not a server-side bulk result.

Source

Thrown at pkg/gofr/datasource/elasticsearch/elasticsearch.go:250

	start := time.Now()
	tracedCtx, span := c.addTrace(ctx, "bulk", nil, "")

	var buf bytes.Buffer
	for _, op := range operations {
		if err := json.NewEncoder(&buf).Encode(op); err != nil {
			return nil, fmt.Errorf("%w: %w", errEncodingOperation, err)
		}
	}

	req := esapi.BulkRequest{
		Body:    &buf,
		Refresh: "true",
	}

	res, err := req.Do(tracedCtx, c.client)
	if err != nil {
		return nil, fmt.Errorf("%w: executing bulk: %w", errOperation, err)
	}

	defer res.Body.Close()

	if res.IsError() {
		return nil, fmt.Errorf("%w: %s", errResponse, res.String())
	}

	var result map[string]any
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return nil, fmt.Errorf("%w: %w", errParsingResponse, err)
	}

	c.sendOperationStats(start, "BULK", nil, "", operations, span)

	return result, nil
}

View on GitHub (pinned to 187eb24962)

Solutions

  1. Unwrap and log the underlying error (errors.Unwrap) to distinguish connection refused vs timeout vs context canceled.
  2. Verify the Elasticsearch endpoint host/port and that the node is up: curl http://host:9200/_cluster/health.
  3. Implement retry with backoff for transient network errors, and use a context with adequate timeout.
  4. Check DNS/container networking and firewall rules if connection refused persists.
  5. Confirm the client was Connected()/initialized before calling Bulk — a nil client produces transport errors.

Example fix

// before
res, err := client.Bulk(ctx, ops)
if err != nil { return err }
// after
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
res, err := client.Bulk(ctx, ops)
if err != nil {
    if isRetryable(err) { // net.Error timeout, connection refused
        return retryWithBackoff(ops)
    }
    return err
}
Defensive patterns

Strategy: retry

Validate before calling

// before calling Bulk, confirm reachability
resp, err := http.Get(esURL + "/_cluster/health")
if err != nil || resp.StatusCode != 200 {
    return fmt.Errorf("elasticsearch unreachable: %v", err)
}

Try / catch

res, err := client.Bulk(ctx, ops)
if err != nil {
    var netErr net.Error
    if errors.As(err, &netErr) || strings.Contains(err.Error(), "connection refused") {
        // retry with exponential backoff; transient network issue
        return backoffRetry(ops, 3)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Bulk() while the Elasticsearch node is unreachable (down, wrong host/port), DNS failure, connection timeouts under load, context cancellation before Do completes, or c.client being nil/misconfigured.

Common situations: ES cluster restart or rolling upgrade during a batch job; wrong ELASTICSEARCH_HOSTS env var; container networking issues in Kubernetes; firewall dropping port 9200; bulk job running past a context deadline.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01). Data as JSON: /api/errors/1910457ef78e4d19. Report an issue: GitHub.