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
- Parse the wrapped res.String() message for the ES exception type.
- For resource_already_exists_exception, check existence first or treat duplicate creation as a no-op.
- For invalid_index_name_exception, use lowercase names without leading underscores, spaces, or forbidden characters.
- For settings rejection, align settings with the cluster's ES version (e.g. type removal in ES 7+/8+).
- 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
- Treat CreateIndex as idempotent; check existence or swallow resource_already_exists_exception.
- Enforce lowercase, valid index names with a shared validation helper.
- Keep settings compatible with the deployed ES version; test migrations against the same version.
- Grant service credentials only the permissions they need, including index management where required.
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
- invalid elasticsearch response
- %w: settings: %w
- error encoding operation
- %w: creating index: %w
- %w: deleting index: %w
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/81328df95765d796.
Report an issue: GitHub.