{"record":{"id":"dfba8f4a2aa49936","repo":"ruby-grape/grape","slug":"group-type-is-required","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/dsl/parameters.rb","lineNumber":151,"sourceCode":"        return require_required_and_optional_fields(attrs.first, using:, except:) if using\n\n        validate_attributes(attrs, **opts, &block)\n        block ? new_scope(attrs.first, type: opts[:type], as: opts[:as], &block) : push_declared_params(attrs, as: opts[:as])\n      end\n\n      # Allow, but don't require, one or more parameters for the current\n      #   endpoint.\n      # @param (see #requires)\n      # @option (see #requires)\n      def optional(*attrs, using: nil, except: nil, **opts, &block)\n        return redispatch_legacy_options(:optional, attrs, { using:, except: }.compact.merge(opts), &block) if legacy_options?(attrs)\n\n        type = opts[:type]\n        opts = @group.deep_merge(opts) if @group\n\n        # check type for optional parameter group\n        if attrs && block\n          raise Grape::Exceptions::MissingGroupType if type.nil?\n          raise Grape::Exceptions::UnsupportedGroupType unless Grape::Validations::Types.group?(type)\n        end\n\n        return require_optional_fields(attrs.first, using:, except:) if using\n\n        validate_attributes(attrs, **opts, &block)\n        block ? new_scope(attrs.first, type: opts[:type], as: opts[:as], optional: true, &block) : push_declared_params(attrs, as: opts[:as])\n      end\n\n      # Define common settings for one or more parameters\n      # @param (see #requires)\n      # @option (see #requires)\n      def with(**opts, &)\n        new_group_attrs = @group&.deep_merge(opts) || opts\n        new_group_scope(new_group_attrs, &)\n      end\n\n      %i[mutually_exclusive exactly_one_of at_least_one_of all_or_none_of].each do |validator|","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/dsl/parameters.rb#L133-L169","documentation":"`optional :name do ... end` opens a nested parameter group, and Grape must know the container's shape to coerce and validate it. When a block is given but no `type:` option is supplied, Grape raises Grape::Exceptions::MissingGroupType ('group type is required') at boot time. The same rule applies to `requires` with a block; only flat attributes may omit the type.","triggerScenarios":"`optional :address do requires :street end` without a type. Copying a nested group example that relies on a default type (Grape has none). Refactoring `optional :address, type: Hash` by dropping the type while keeping the block.","commonSituations":"First-time use of nested params. Migrating from Grape versions or other frameworks (Rails strong params) where the container type is implicit. Renaming group parameters and accidentally removing the type option.","solutions":["Add `type: Hash` for a single nested object: `optional :address, type: Hash do ... end`.","Use `type: Array` for a list of objects, or `type: JSON` / `type: Array[JSON]` for JSON payloads."],"exampleFix":"# before\noptional :address do\n  requires :street, type: String\nend # raises MissingGroupType\n\n# after\noptional :address, type: Hash do\n  requires :street, type: String\nend","handlingStrategy":"validation","validationCode":"# Convention: every params block paired with `optional/requires ... do` MUST carry a group type\n# Enforce in review/lint: grep for blocks without type:\n#   grep -nE '(optional|requires)\\s+:\\w+(\\s*,\\s*)?do' config/api - shows suspicious declarations","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Memorize the rule: block on a param declaration means `type: Hash|Array|JSON|Array[JSON]` is mandatory.","Extract a macro (e.g. `optional_hash :address do`) in a base class so groups always carry the type.","Boot every endpoint in a spec (one request per route) so definition-time exceptions fail CI."],"tags":["grape","params","optional","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"}