redis/redis-rb · error · ArgumentError
Invalid schema
Error message
Invalid schema
What it means
Index.create (and Redis#create_index) require the third argument to be a Redis::Commands::Search::Schema instance: the object that renders the SCHEMA clause tokens for FT.CREATE. A bare array of field objects, a hash, or a single field raises ArgumentError before anything is sent (lib/redis/commands/modules/search/index.rb:50). Build one with Schema.new(fields) or the Schema.build block DSL.
Source
Thrown at lib/redis/commands/modules/search/index.rb:50
# Create the index on the server (runs +FT.CREATE+) and return a handle to it.
#
# @example
# Redis::Commands::Search::Index.create(redis, "idx", schema, "hash", prefix: "doc")
#
# @param redis [Redis] the client to use
# @param name [String] the index name
# @param schema [Schema] the field schema
# @param storage_type [String] the indexed data type (+"hash"+ or +"json"+)
# @param prefix [String, nil] key prefix for documents
# @param stopwords [Array<String>, nil] custom stopword list
# @param skip_initial_scan [Boolean] do not backfill existing keys (+SKIPINITIALSCAN+)
# @return [Index] the created index
# @raise [ArgumentError] if +schema+ is not a {Schema}
def self.create(
redis, name, schema, storage_type,
prefix: nil, stopwords: nil, skip_initial_scan: false, **options
)
raise ArgumentError, "Invalid schema" unless schema.is_a?(Schema)
redis.ft_create(
name, schema, storage_type,
prefix: prefix, stopwords: stopwords,
skip_initial_scan: skip_initial_scan, **options
)
# The Index stores the *literal* key prefix it prepends to (and strips from) document
# ids. A definition (which FT.CREATE prefers over the +prefix:+ keyword) carries its
# prefixes verbatim, e.g. "bicycle:"; the +prefix:+ keyword form appends the ":". It also
# records the resolved storage type (HASH/JSON) so #add writes documents the right way.
new(
redis, name, schema, resolve_storage_type(storage_type, options[:definition]),
prefix: key_prefix(prefix, options[:definition]), stopwords: stopwords
)
end
# The single literal key prefix the Index should manage, or nil when it can't be
# determined unambiguously (no prefix, or a definition with several prefixes).View on GitHub (pinned to 2ba9010b91)
Solutions
- Wrap fields: Schema.new([TextField.new("title"), NumericField.new("price")])
- Or use the block DSL: Schema.build { text_field "title"; numeric_field "price" }
- Type-check deserialized schema config before calling Index.create
Example fix
// before
Index.create(redis, "idx", [TextField.new("title")], "hash")
// after
Index.create(redis, "idx", Schema.new([TextField.new("title")]), "hash") Defensive patterns
Strategy: type-guard
Validate before calling
schema = Schema.new(fields) unless schema.is_a?(Redis::Commands::Search::Schema) Index.create(redis, name, schema, storage)
Type guard
schema.is_a?(Redis::Commands::Search::Schema)
Try / catch
begin Index.create(redis, name, schema, storage) rescue ArgumentError => e raise ConfigError, "schema must be built with Schema.new or Schema.build" end
Prevention
- Construct schemas via Schema.build so the type is always right
- Type-check schema objects deserialized from config before use
- Keep one factory method that always returns a Schema instance
When it happens
Trigger: Index.create(redis, "idx", [TextField.new("title")], "hash"); passing the SchemaDefinition DSL object instead of the Schema that Schema.build returns; passing a Hash of name => field pairs from deserialized config.
Common situations: Assuming the API accepts a plain field list because raw FT.CREATE does; refactoring from legacy ft_create(name, *fields) call sites; schema config stored as JSON and reconstructed as the wrong type.
Related errors
- Invalid phonetic matcher. Supported matchers are: #{valid_ma
- Realtime vector indexing supporting 3 Indexing Methods: 'FLA
- collect fields must be :all or a non-empty list
- Vector fields cannot be sortable
- Vector fields cannot have no_index option
AI-assisted analysis of redis/redis-rb@2ba9010b91 (2026-08-23).
Data as JSON: /api/errors/52f73de99c08a9bd.
Report an issue: GitHub.