flippercloud/flipper · error · RuntimeError
Your database needs to be migrated to use the latest Flipper
Error message
Your database needs to be migrated to use the latest Flipper features. Run `rails generate flipper:update` and `rails db:migrate`.
What it means
The ActiveRecord adapter stores JSON-typed gate values (feature expressions) in the flipper_gates.value column, which must be a :text column of unlimited length. Before writing a JSON gate, set() checks value_not_text? (column_for_attribute(:value).type != :text, see PR #692) and raises VALUE_TO_TEXT_WARNING when the schema is still the old string/varchar shape. The adapter refuses to write rather than risk truncated/corrupt JSON. Reads of every other gate type keep working, so the error only surfaces once code starts enabling expression (JSON) gates.
Source
Thrown at lib/flipper/adapters/active_record.rb:211
def unsupported_data_type(data_type)
raise "#{data_type} is not supported by this adapter"
end
private
def model_class(default_class, table_prefix, table_name)
return default_class if table_prefix.nil?
Class.new(default_class) do
self.table_name = "#{table_prefix}#{table_name}"
end
end
def set(feature, gate, thing, options = {})
clear_feature = options.fetch(:clear, false)
json_feature = options.fetch(:json, false)
raise VALUE_TO_TEXT_WARNING if json_feature && value_not_text?
with_write_connection(@gate_class) do
@gate_class.transaction(requires_new: true) do
clear(feature) if clear_feature
delete(feature, gate)
begin
@gate_class.create! do |g|
g.feature_key = feature.key
g.key = gate.key
g.value = json_feature ? Typecast.to_json(thing.value) : thing.value.to_s
end
rescue ::ActiveRecord::RecordNotUnique
# assume this happened concurrently with the same thing and its fine
# see https://github.com/flippercloud/flipper/issues/544
end
end
end
View on GitHub (pinned to 1f86de3ec9)
Solutions
- Run `rails generate flipper:update && rails db:migrate` in the affected environment — this migrates flipper_gates.value to text.
- Do the same for test/CI databases (`rails db:test:prepare` or RAILS_ENV=test rails db:migrate) so specs do not hit the old schema.
- Verify the fix: check the column type via ActiveRecord::Base.connection.columns(:flipper_gates) and confirm the `value` column reports :text.
- If it still raises after migrating, check that the adapter was not built with a custom gate_class or table_prefix that points at a different, unmigrated gates table.
Example fix
# before
Flipper.enable_expression(:search, Flipper.property(:plan).eq("pro"))
# => RuntimeError: Your database needs to be migrated to use the latest Flipper features.
# after — run once per environment
# rails generate flipper:update
# rails db:migrate
Flipper.enable_expression(:search, Flipper.property(:plan).eq("pro")) # works Defensive patterns
Strategy: validation
Validate before calling
def flipper_gates_value_is_text?
column = ActiveRecord::Base.connection.columns(:flipper_gates).find { |c| c.name == "value" }
column&.type == :text
end
raise "Run rails generate flipper:update && rails db:migrate before enabling expressions" unless flipper_gates_value_is_text? Try / catch
begin
Flipper.enable_expression(:search, expr)
rescue RuntimeError => e
raise unless e.message.include?("rails generate flipper:update")
# block expression usage until the migration ships
end Prevention
- Run flipper:update migrations in every environment (including test/CI) as part of gem upgrades.
- Add a boot-time column-type check that fails fast before traffic uses expression flags.
- Keep flipper migrations in the normal db/migrate pipeline, not a separate optional path.
- Smoke-test one expression enable in staging before rolling out expression-based code.
When it happens
Trigger: feature.enable_expression / Flipper.enable_expression(...), feature.add_expression, or any write whose gate data_type is :json (set(..., json: true)) — including the cache_write path — against a database where flipper_gates.value is still string/varchar instead of text.
Common situations: Upgrading flipper-active_record to a version with expression gates without running the new migration; a long-lived app whose flipper tables were generated years ago; CI or staging databases restored from an old schema dump; deploying code that uses Flipper expressions before the flipper:update migration has run in that environment; a custom gate_class/table_prefix pointing at a table nobody migrated.
Related errors
- Group #{name.inspect} has already been registered
- Actor limit of #{@limit} exceeded for feature #{feature.key}
- Failed with status: #{response.code}
- #{data_type} is not supported by this adapter
- #{gate} is not supported by this adapter yet
AI-assisted analysis of flippercloud/flipper@1f86de3ec9 (2026-08-23).
Data as JSON: /api/errors/648b33a20267ce41.
Report an issue: GitHub.