gofr-dev/gofr · critical

%w: creating index: %w

Error message

%w: creating index: %w

What it means

This is errOperation wrapped around the error from esapi.IndicesCreateRequest.Do in CreateIndex. It means the HTTP request to Elasticsearch never completed at the transport layer: connection refused, DNS failure, TLS error, timeout, or a cancelled context. No HTTP response was produced, unlike errResponse cases.

Source

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

	}

	start := time.Now()

	tracedCtx, span := c.addTrace(ctx, "create-index", []string{index}, "")

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

	req := esapi.IndicesCreateRequest{
		Index: index,
		Body:  bytes.NewReader(body),
	}

	res, err := req.Do(tracedCtx, c.client)
	if err != nil {
		return fmt.Errorf("%w: creating index: %w", errOperation, err)
	}
	defer res.Body.Close()

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

	c.sendOperationStats(start, fmt.Sprintf("CREATE INDEX %s", index),
		[]string{index}, "", settings, span)

	return nil
}

func (c *Client) DeleteIndex(ctx context.Context, index string) error {
	if strings.TrimSpace(index) == "" {
		return errEmptyIndex
	}

View on GitHub (pinned to 187eb24962)

Solutions

  1. Verify Config.Addresses points at a reachable ES HTTP endpoint (default port 9200).
  2. Check cluster/container health: curl the ES endpoint directly from the app host.
  3. Confirm Connect() succeeded and the health check passed at startup.
  4. Inspect the inner wrapped error for connection refused vs DNS vs timeout to target the fix.
  5. Ensure the passed context has sufficient deadline and is not already cancelled.

Example fix

// before
err := client.CreateIndex(ctx, "orders", settings) // ctx already cancelled
// after
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
err := client.CreateIndex(ctx, "orders", settings)
Defensive patterns

Strategy: retry

Validate before calling

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

Try / catch

var lastErr error
for attempt := 0; attempt < 3; attempt++ {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    err := client.CreateIndex(ctx, index, settings)
    cancel()
    if err == nil {
        break
    }
    lastErr = err
    if strings.Contains(err.Error(), "elasticsearch operation error") {
        time.Sleep(time.Duration(attempt+1) * time.Second) // transport error: retry
        continue
    }
    return err // non-transport error: do not retry
}
return lastErr

Prevention

When it happens

Trigger: Calling CreateIndex when the ES cluster is unreachable: wrong Addresses in Config, cluster down, network/firewall blocking the port, client not yet connected (Connect() failed and c.client is effectively unusable), or the ctx passed in is already cancelled/expired.

Common situations: Developers hit this in dev environments where ES runs in Docker but the app uses localhost incorrectly, after a cluster restart, with wrong port (9200 vs 9300), during TLS misconfiguration, or when a short request context expires before the call finishes.

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