weaviate/weaviate · error

property %q already has a filterable index

Error message

property %q already has a filterable index

What it means

The enable-filterable reindex operation requires the target property to NOT already have a filterable inverted index. validateEnableFilterableProperty rejects the request when prop.IndexFilterable is non-nil and true, because there is nothing to enable — the index already exists. This guard prevents pointless reindex jobs and duplicate-index state on the shard.

Source

Thrown at adapters/handlers/rest/handlers_reindex.go:139

// indexing enabled (otherwise there's nothing to rebuild — the caller
// wants enable-rangeable instead). Type must still be numeric/date.
func validateRebuildRangeableProperty(prop *models.Property) error {
	if !isNumericProperty(prop) {
		return fmt.Errorf("property %q is not a numeric type (int, number, date)", prop.Name)
	}
	if prop.IndexRangeFilters == nil || !*prop.IndexRangeFilters {
		return fmt.Errorf("property %q does not have a rangeable index to rebuild; use enable to create one", prop.Name)
	}
	return nil
}

// validateEnableFilterableProperty validates that the property is a
// suitable target for enable-filterable: it must not already have a
// filterable index, and its data type must support inverted filtering
// (everything except blob, geoCoordinates, and references).
func validateEnableFilterableProperty(prop *models.Property) error {
	if prop.IndexFilterable != nil && *prop.IndexFilterable {
		return fmt.Errorf("property %q already has a filterable index", prop.Name)
	}
	dt, ok := entschema.AsPrimitive(prop.DataType)
	if !ok {
		// Non-primitive (references) — not supported for filterable enable.
		return fmt.Errorf("property %q type %v does not support a filterable index", prop.Name, prop.DataType)
	}
	// Allow every primitive type EXCEPT the three below. Using a default
	// keeps the allow-list implicit so newly-added primitive types are
	// permitted by default; only types we have positively decided cannot
	// support a filterable index need to be listed.
	switch dt {
	case entschema.DataTypeBlob, entschema.DataTypeGeoCoordinates, entschema.DataTypePhoneNumber:
		return fmt.Errorf("property %q type %q does not support a filterable index", prop.Name, dt)
	default:
		return nil
	}
}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Check prop.IndexFilterable before issuing the enable-filterable request and skip if already true
  2. Use a repair/rebuild-filterable operation instead if you want to rebuild the existing index
  3. Update automation scripts to treat this condition as a no-op success

Example fix

// before
client.Reindex().EnableFilterable(class, "description") // unconditional
// after
if prop.IndexFilterable == nil || !*prop.IndexFilterable {
  client.Reindex().EnableFilterable(class, "description")
}
Defensive patterns

Strategy: validation

Validate before calling

if prop.IndexFilterable != nil && *prop.IndexFilterable {
  return // already filterable; skip enable-filterable call
}

Type guard

func needsFilterableEnable(p *models.Property) bool { return p.IndexFilterable == nil || !*p.IndexFilterable }

Try / catch

if err := enableFilterable(class, prop); err != nil && strings.Contains(err.Error(), "already has a filterable index") {
  // treat as no-op success
}

Prevention

When it happens

Trigger: Calling the enable-filterable reindex endpoint (resolveFilterableUpsert path) with a property whose schema already has IndexFilterable set to true.

Common situations: Re-running an enable-filterable request that already succeeded; scripting schema migrations without idempotency checks; syncing schema from another environment where filterable was already enabled.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/b3710a214d8c1549. Report an issue: GitHub.