{"record":{"id":"dc0f3a2c0a803ddb","repo":"activerecord-hackery/ransack","slug":"no-valid-predicate-for-key","errorCode":null,"errorMessage":"No valid predicate for #{key}","messagePattern":"No valid predicate for #(.+?)","errorType":"exception","errorClass":"InvalidSearchError","httpStatus":null,"severity":"error","filePath":"lib/ransack/nodes/condition.rb","lineNumber":43,"sourceCode":"            # TODO: Figure out what to do with multiple types of attributes,\n            # if anything. Tempted to go with \"garbage in, garbage out\" here.\n            if predicate.validate(condition.values, condition.default_type)\n              condition\n            else\n              nil\n            end\n          end\n        end\n\n        private\n\n          def extract_values_for_condition(key, context = nil)\n            str = key.dup\n            name = Predicate.detect_and_strip_from_string!(str)\n            predicate = Predicate.named(name)\n\n            unless predicate || Ransack.options[:ignore_unknown_conditions]\n              raise InvalidSearchError, \"No valid predicate for #{key}\"\n            end\n\n            if context.present?\n              str = context.ransackable_alias(str)\n            end\n\n            combinator =\n            if str.match(/_(or|and)_/)\n              $1\n            else\n              nil\n            end\n\n            if context.present? && context.attribute_method?(str)\n              attributes = [str]\n            else\n              attributes = str.split(/_and_|_or_/)\n            end","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/activerecord-hackery/ransack/blob/e82f6bab3956c5597e7debbefa218d9e94e58ceb/lib/ransack/nodes/condition.rb#L25-L61","documentation":"While parsing each q[...] condition key, Ransack strips a trailing predicate suffix (like _cont or _gteq) and looks it up with Predicate.named. If no known predicate remains — because the key has no suffix or an unrecognized one — Ransack raises InvalidSearchError, but only when unknown conditions are not being ignored (ransack! or ignore_unknown_conditions = false; plain Model.ransack ignores them by default).","triggerScenarios":"Person.ransack!('name' => 'x') — key lacks a predicate suffix; a typo'd predicate like name_conct or value_gte (missing q); a custom predicate used in the form but never registered via Ransack.configure { config.add_predicate }; URL params crafted or truncated by hand (q[c][0][a]=name with no _eq).","commonSituations":"Using strict ransack! in controllers to surface bad params; renaming/removing a custom predicate while view forms still submit the old suffix; hand-built search URLs missing suffixes; Ransack upgrades where a predicate name changed.","solutions":["Append a valid predicate suffix to the attribute key: name_cont, created_at_gteq, etc. (see Ransack::Translate or the wiki predicate list)","If the predicate should exist, register it: Ransack.configure { |c| c.add_predicate(:my_pred, arel_predicate: 'eq') }","If junk params are expected, use the non-strict Person.ransack(params[:q]) which ignores unknown conditions, or set Ransack.configure { |c| c.ignore_unknown_conditions = true }","Rescue Ransack::InvalidSearchError in the controller and fall back to an unfiltered result for malformed user input"],"exampleFix":"# before\nPerson.ransack!(name: 'Alice')\n# => Ransack::InvalidSearchError: No valid predicate for name\n\n# after\nPerson.ransack!(name_cont: 'Alice')","handlingStrategy":"try-catch","validationCode":"KNOWN_PREDICATES = %w[eq not_eq cont start end gt lt gteq lteq in not_in null not_null true false present blank matches does_not_match].freeze\n\ndef sanitized_ransack_params(raw)\n  raw.select do |key, _|\n    key == 's' || key == 'sorts' ||\n      key.to_s.split(/_(or|and)_/).all? { |part|\n        part.match?(/_(#{KNOWN_PREDICATES.join('|')})$/)\n      }\n  end\nend\n\nPerson.ransack!(sanitized_ransack_params(params[:q]))","typeGuard":"def valid_condition_key?(key)\n  Ransack::Predicate.named(\n    Ransack::Predicate.detect_and_strip_from_string!(key.dup)\n  ).present?\nend","tryCatchPattern":"begin\n  @q = Person.ransack!(params[:q])\n  @people = @q.result\nrescue Ransack::InvalidSearchError => e\n  flash.now[:alert] = 'Invalid search filters; showing all records.'\n  Rails.logger.info(\"Bad ransack params: #{e.message}\")\n  @q = Person.ransack\n  @people = Person.all\nend","preventionTips":["Standardize search inputs on Ransack's form helpers so every field name ends in a valid predicate","Register custom predicates in an initializer so forms and parsing agree","Reserve ransack! for trusted/internal callers; use ransack for end-user facing endpoints, or rescue InvalidSearchError as a 4xx"],"tags":["ruby","rails","ransack","predicates","search-params","invalidsearcherror"],"backgroundTag":"unknown-search-parameter","analyzedSha":"e82f6bab3956c5597e7debbefa218d9e94e58ceb","analyzedAt":"2026-08-21T19:30:23.639Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}