gofr-dev/gofr · error

elasticsearch operation error

Error message

elasticsearch operation error

What it means

In extractNestedClaim, each dot-separated segment must resolve to a map (map[string]any or jwt.MapClaims). If the current value is some other type (string, number, array, bool), the library wraps errInvalidClaimStructure with the traversed prefix path. This is a shape error: a mid-path segment is a scalar where a nested object is required.

Solutions

  1. Fix the token issuer so intermediate segments are JSON objects
  2. Adjust the path to match the real structure (e.g. treat a JSON-string claim by decoding it separately rather than traversing it)
  3. Pre-validate token payload shape with a test fixture asserting the nested object structure

Example fix

// before
{"permissions": "read,write"} // path: permissions.role
// after
{"permissions": {"role": "admin"}}
Defensive patterns

Strategy: type-guard

Validate before calling

node, ok := claims["permissions"]
if !ok { return fmt.Errorf("permissions missing") }
if _, ok := node.(map[string]any); !ok {
    return fmt.Errorf("permissions must be a nested object")
}

Type guard

func isNestedMap(v any) bool {
    switch v.(type) {
    case map[string]any, jwt.MapClaims:
        return true
    }
    return false
}

Try / catch

v, err := extractClaimValue(claims, "permissions.role")
if errors.Is(err, errInvalidClaimStructure) {
    // token shape invalid: reject with 401 and log prefix
}

Prevention

When it happens

Trigger: Path "permissions.role" where claims["permissions"] is a JSON string or array rather than an object; intermediate segment exists but holds a scalar (e.g. "meta.version.name" where meta.version is "1.2").

Common situations: IdP stores permissions as a JSON-encoded string instead of an object; schema drift after an auth-service refactor; misremembered claim layout in config.

Related errors


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

Appendix: source

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

	es "github.com/elastic/go-elasticsearch/v8"
	"github.com/elastic/go-elasticsearch/v8/esapi"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
)

const (
	statusDown     = "DOWN"
	statusUp       = "UP"
	defaultTimeout = 5 * time.Second
)

var (
	errEmptyIndex        = errors.New("index name cannot be empty")
	errEmptyDocumentID   = errors.New("document ID cannot be empty")
	errEmptyQuery        = errors.New("query cannot be empty")
	errEmptyOperations   = errors.New("operations cannot be empty")
	errHealthCheckFailed = errors.New("elasticsearch health check failed")
	errOperation         = errors.New("elasticsearch operation error")
	errMarshaling        = errors.New("error marshaling data")
	errParsingResponse   = errors.New("error parsing response")
	errResponse          = errors.New("invalid elasticsearch response")
	errEncodingOperation = errors.New("error encoding operation")
)

// Config holds the configuration for connecting to Elasticsearch.
type Config struct {
	Addresses []string
	Username  string
	Password  string
}

// Client represents the Elasticsearch client.
type Client struct {
	config  Config
	client  *es.Client
	logger  Logger

View on GitHub (pinned to 187eb24962)