{"record":{"id":"63126d1255fb5c98","repo":"ruby-grape/grape","slug":"oneof-must-be-a-non-empty-array-of-blocks","errorCode":null,"errorMessage":"oneof: must be a non-empty Array of blocks","messagePattern":"oneof: must be a non-empty Array of blocks","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/grape/validations/params_scope.rb","lineNumber":407,"sourceCode":"        # configuration[:some_type] evaluates to nil. Skipping instantiation\n        # here is correct — the real mounted instance will replay this step\n        # with the actual type value.\n        return unless coerce_options.type\n\n        validate('coerce', coerce_options, attrs, spec.required?, spec.shared_opts)\n      end\n\n      # Translate a `oneof: [proc, proc, ...]` declaration into a list of\n      # captured validator arrays — one array per variant. Each variant's\n      # block is evaluated in its own +ParamsScope+ backed by an\n      # {OneofCollector} so the full params DSL is available inside variants\n      # and the resulting validators are kept out of the real API's\n      # registration list.\n      def process_oneof!(validations)\n        raise ArgumentError, 'oneof: requires type: Hash' unless validations[:type] == Hash\n\n        variants = validations[:oneof]\n        raise ArgumentError, 'oneof: must be a non-empty Array of blocks' unless variants.is_a?(Array) && variants.any?\n        raise ArgumentError, 'oneof: each variant must be a Proc' unless variants.all?(Proc)\n\n        validations[:oneof] = variants.map { |block| OneofCollector.collect(block) }\n      end\n\n      def validate(type, options, attrs, required, opts)\n        validator_class = Validations.require_validator(type)\n        validator_instance = validator_class.new(\n          attrs,\n          options,\n          required,\n          self,\n          opts\n        )\n        @api.inheritable_setting.add_validation(validator_instance)\n      end\n\n      def all_element_blank?(scoped_params)","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/validations/params_scope.rb#L389-L425","documentation":"`process_oneof!` requires the `oneof:` value to be a non-empty Array so there is at least one alternative to validate against. `nil`, an empty Array, or a bare (unwrapped) Proc all fail `variants.is_a?(Array) && variants.any?` and raise ArgumentError at API-definition time.","triggerScenarios":"`oneof: []`; `oneof: nil`; `requires :filter, type: Hash, oneof: -> { requires :id }` (a single proc not wrapped in an Array).","commonSituations":"Dynamically building the variant list and passing through an empty result when no variants apply; forgetting the extra brackets around a single alternative.","solutions":["Wrap variants in an Array with at least one element: `oneof: [-> { requires :id }, -> { requires :name }]`","Wrap a single alternative: `oneof: [-> { requires :id }]`","If there are no real alternatives, delete the `oneof:` key entirely"],"exampleFix":"# before\nrequires :filter, type: Hash, oneof: variants # variants == [] at load time\n\n# after\nrequires :filter, type: Hash, oneof: [\n  -> { requires :id, type: Integer },\n  -> { requires :name, type: String }\n]","handlingStrategy":"validation","validationCode":"def oneof_variants_present?(opts)\n  variants = opts[:oneof]\n  variants.is_a?(Array) && !variants.empty?\nend\n\nraise ArgumentError, 'oneof needs at least one variant' unless oneof_variants_present?(filter_opts)","typeGuard":null,"tryCatchPattern":"begin\n  requires :filter, type: Hash, oneof: build_variants # may return []\nrescue ArgumentError => e\n  raise \"oneof built no variants for :filter: #{e.message}\"\nend","preventionTips":["When generating variant lists dynamically, fall back to a normal declaration when the list is empty","Wrap single alternatives in `[...]` by convention","Spec-test generated declarations for every branch that builds oneof lists"],"tags":["grape","params","oneof","validation","argumenterror","dsl"],"backgroundTag":"oneof-validation-misconfigured","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}