gofr-dev/gofr · error

%w: %s

Error message

%w: %s

What it means

Same sentinel errResponse as index 10, raised in CreateIndex: the cluster responded with an HTTP error status for the create-index request. The raw ES response (including its error body) is appended via res.String(), so the precise exception type is in the message.

Source

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

	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
	}

	start := time.Now()

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

	req := esapi.IndicesDeleteRequest{

View on GitHub (pinned to 187eb24962)

Solutions

  1. Parse the wrapped res.String() message for the ES exception type.
  2. For resource_already_exists_exception, check existence first or treat duplicate creation as a no-op.
  3. For invalid_index_name_exception, use lowercase names without leading underscores, spaces, or forbidden characters.
  4. For settings rejection, align settings with the cluster's ES version (e.g. type removal in ES 7+/8+).
  5. For 401/403, fix credentials or grant index management permissions.

Example fix

// before
err := client.CreateIndex(ctx, "Orders", settings) // invalid index name
// after
err := client.CreateIndex(ctx, strings.ToLower(indexName), settings)
Defensive patterns

Strategy: type-guard

Validate before calling

// validate index name before the call
var indexNameRe = regexp.MustCompile(`^[a-z0-9][a-z0-9_.-]*$`)
if !indexNameRe.MatchString(index) {
    return fmt.Errorf("invalid index name: %q", index)
}

Type guard

func IsIndexAlreadyExists(err error) bool {
    return strings.Contains(err.Error(), "resource_already_exists_exception")
}

Try / catch

if err := client.CreateIndex(ctx, index, settings); err != nil {
    if IsIndexAlreadyExists(err) {
        return nil // idempotent create
    }
    return fmt.Errorf("create index %s failed: %w", index, err)
}

Prevention

When it happens

Trigger: CreateIndex(ctx, index, settings) where ES rejects the request: index already exists (resource_already_exists_exception), invalid index name (invalid_index_name_exception, e.g. uppercase or illegal characters), invalid settings payload rejected by the cluster (e.g. unknown analyzer or bad number_of_shards value), or 401/403 from insufficient permissions.

Common situations: Developers hit this when running migrations twice, using uppercase or wildcard-invalid index names, referencing a custom analyzer not defined in settings, or deploying with credentials lacking index-admin rights.

Related errors


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