{"record":{"id":"648b33a20267ce41","repo":"flippercloud/flipper","slug":"your-database-needs-to-be-migrated-to-use-the-late","errorCode":null,"errorMessage":"Your database needs to be migrated to use the latest Flipper features.\nRun `rails generate flipper:update` and `rails db:migrate`.","messagePattern":"Your database needs to be migrated to use the latest Flipper features\\.\nRun `rails generate flipper:update` and `rails db:migrate`\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/flipper/adapters/active_record.rb","lineNumber":211,"sourceCode":"      def unsupported_data_type(data_type)\n        raise \"#{data_type} is not supported by this adapter\"\n      end\n\n      private\n\n      def model_class(default_class, table_prefix, table_name)\n        return default_class if table_prefix.nil?\n\n        Class.new(default_class) do\n          self.table_name = \"#{table_prefix}#{table_name}\"\n        end\n      end\n\n      def set(feature, gate, thing, options = {})\n        clear_feature = options.fetch(:clear, false)\n        json_feature = options.fetch(:json, false)\n\n        raise VALUE_TO_TEXT_WARNING if json_feature && value_not_text?\n\n        with_write_connection(@gate_class) do\n          @gate_class.transaction(requires_new: true) do\n            clear(feature) if clear_feature\n            delete(feature, gate)\n            begin\n              @gate_class.create! do |g|\n                g.feature_key = feature.key\n                g.key = gate.key\n                g.value = json_feature ? Typecast.to_json(thing.value) : thing.value.to_s\n              end\n            rescue ::ActiveRecord::RecordNotUnique\n              # assume this happened concurrently with the same thing and its fine\n              # see https://github.com/flippercloud/flipper/issues/544\n            end\n          end\n        end\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/flippercloud/flipper/blob/1f86de3ec91521585b156445e156642938b19cb0/lib/flipper/adapters/active_record.rb#L193-L229","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nFlipper.enable_expression(:search, Flipper.property(:plan).eq(\"pro\"))\n# => RuntimeError: Your database needs to be migrated to use the latest Flipper features.\n\n# after — run once per environment\n# rails generate flipper:update\n# rails db:migrate\nFlipper.enable_expression(:search, Flipper.property(:plan).eq(\"pro\")) # works","handlingStrategy":"validation","validationCode":"def flipper_gates_value_is_text?\n  column = ActiveRecord::Base.connection.columns(:flipper_gates).find { |c| c.name == \"value\" }\n  column&.type == :text\nend\n\nraise \"Run rails generate flipper:update && rails db:migrate before enabling expressions\" unless flipper_gates_value_is_text?","typeGuard":null,"tryCatchPattern":"begin\n  Flipper.enable_expression(:search, expr)\nrescue RuntimeError => e\n  raise unless e.message.include?(\"rails generate flipper:update\")\n  # block expression usage until the migration ships\nend","preventionTips":["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."],"tags":["ruby","flipper","active-record","migration","schema-drift","expression-flags"],"backgroundTag":"pending-database-migration","analyzedSha":"1f86de3ec91521585b156445e156642938b19cb0","analyzedAt":"2026-08-23T04:36:09.896Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}