gofr-dev/gofr · critical

%w: executing search: %w

Error message

%w: executing search: %w

What it means

This is errOperation wrapped around the transport error from esapi.SearchRequest.Do. The search request failed before an HTTP response was produced: unreachable cluster, connection reset, TLS failure, or context deadline exceeded. The inner wrapped error distinguishes the transport cause.

Source

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

	}

	start := time.Now()

	tracedCtx, span := c.addTrace(ctx, "search", indices, "")

	body, err := json.Marshal(query)
	if err != nil {
		return nil, fmt.Errorf("%w: query: %w", errMarshaling, err)
	}

	req := esapi.SearchRequest{
		Index: indices,
		Body:  bytes.NewReader(body),
	}

	res, err := req.Do(tracedCtx, c.client)
	if err != nil {
		return nil, fmt.Errorf("%w: executing search: %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, "SEARCH", indices, "", query, span)

	return result, nil
}

View on GitHub (pinned to 187eb24962)

Solutions

  1. Check cluster reachability (curl the endpoint) and Config.Addresses correctness.
  2. Inspect the inner wrapped error: connection refused vs timeout vs TLS to target the fix.
  3. Increase the context deadline or optimize the query (fewer fields, pagination, aggregations tuning) if timing out.
  4. Add retry-with-backoff for transient connection resets.
  5. Verify startup Connect()/HealthCheck succeeded before issuing searches.

Example fix

// before
res, err := client.Search(ctx, []string{"orders"}, bigAggregationQuery) // context deadline exceeded
// after
qctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
res, err := client.Search(qctx, []string{"orders"}, optimizedQuery)
Defensive patterns

Strategy: retry

Validate before calling

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if _, err := client.HealthCheck(ctx); err != nil {
    return nil, fmt.Errorf("elasticsearch unavailable: %w", err)
}

Try / catch

var result map[string]any
var err error
for attempt := 0; attempt < 3; attempt++ {
    qctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    result, err = client.Search(qctx, indices, query)
    cancel()
    if err == nil {
        break
    }
    if strings.Contains(err.Error(), "executing search") { // transport-level
        time.Sleep(backoff(attempt))
        continue
    }
    break // non-transport errors are not retryable
}

Prevention

When it happens

Trigger: Calling Search when the ES cluster is unreachable or down, DNS fails, the port is wrong, Connect() never succeeded, the context times out before the query completes (common with expensive queries), or a load balancer drops the connection.

Common situations: Developers hit this in production when ES is restarted or under load and expensive queries exceed context deadlines, in k8s when service DNS/name is wrong, or in tests where the ES container isn't ready.

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/a59e44d73ac3f37f. Report an issue: GitHub.