{"record":{"id":"28fc24ddc3a2157c","repo":"ruby-grape/grape","slug":"group-type-is-required-28fc24","errorCode":null,"errorMessage":"group type is required","messagePattern":"group type is required","errorType":"exception","errorClass":"Grape::Exceptions::MissingGroupType","httpStatus":null,"severity":"error","filePath":"lib/grape/validations/params_scope.rb","lineNumber":282,"sourceCode":"      end\n\n      def validate_attributes(attrs, **opts, &block)\n        opts[:type] ||= Array if block\n        validates(attrs, opts)\n      end\n\n      # Returns a new parameter scope, subordinate to the current one and nested\n      # under the given element.\n      # @param element [Symbol] the parameter name under which this scope is nested\n      # @param type [Class] the type governing this scope\n      # @param as [Symbol, nil] optional renamed name for the element\n      # @param optional [Boolean] whether the parameter this scope is nested under\n      #   is optional or not (and hence, whether this block's params will be).\n      # @yield parameter scope\n      def new_scope(element, type:, as:, optional: false, &)\n        # if required params are grouped and no type or unsupported type is provided, raise an error\n        if element && !optional\n          raise Grape::Exceptions::MissingGroupType if type.nil?\n          raise Grape::Exceptions::UnsupportedGroupType unless Grape::Validations::Types.group?(type)\n        end\n\n        self.class.new(\n          api: @api,\n          element:,\n          element_renamed: as,\n          parent: self,\n          optional:,\n          type: type || Array,\n          group: @group,\n          &\n        )\n      end\n\n      # Returns a new parameter scope, not nested under any current-level param\n      # but instead at the same level as the current scope.\n      # @param dependent_on [Symbol] if given, specifies that this scope should","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/validations/params_scope.rb#L264-L300","documentation":"`requires :name do ... end` creates a subordinate ParamsScope via new_scope, and for a required element Grape must know the group's container type to coerce and validate it. When `type:` is nil (and the scope is not optional), new_scope raises Grape::Exceptions::MissingGroupType ('group type is required') while the endpoint is being defined.","triggerScenarios":"`requires :address do requires :street, type: String end` without a type. Nesting groups where an inner `requires :items do ... end` lost its `type: Array`. Shared param macros that forward blocks but drop the type option.","commonSituations":"Writing nested params for the first time (flat attributes need no type, groups do). Refactoring that removes the type option while keeping the block. Reusing documented examples that predate strict group typing.","solutions":["Add `type: Hash` for a single nested object: `requires :address, type: Hash do ... end`.","Use `type: Array` (or JSON / Array[JSON]) for list-shaped groups.","If the parameter is genuinely optional, switch to `optional :name, type: Hash do ... end`."],"exampleFix":"# before\nrequires :address do\n  requires :street, type: String\nend # raises MissingGroupType\n\n# after\nrequires :address, type: Hash do\n  requires :street, type: String\nend","handlingStrategy":"validation","validationCode":"# Every `requires :x do ... end` must read `requires :x, type: Hash|Array|JSON|Array[JSON] do ... end`\n# Lint: flag any (optional|requires) ... do block lacking type: in params declarations","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat `type:` as mandatory whenever a block follows requires/optional.","Provide base-class macros (e.g. `requires_hash :address`) so groups are always typed.","Boot-time smoke specs per route catch MissingGroupType in CI."],"tags":["grape","params","requires","group-type","nested-params"],"backgroundTag":"missing-group-type","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}