{"record":{"id":"e3d1031fb30dbb92","repo":"ruby-grape/grape","slug":"representation-of-type-representation-class-can","errorCode":null,"errorMessage":"Representation of type #{representation.class} cannot be merged.","messagePattern":"Representation of type #(.+?) cannot be merged\\.","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/grape/dsl/entity.rb","lineNumber":37,"sourceCode":"      # @param options [Hash] additional options forwarded to the entity's `represent` call.\n      #\n      # @example\n      #\n      #   get '/users/:id' do\n      #     present User.find(params[:id]),\n      #       with: API::Entities::User,\n      #       admin: current_user.admin?\n      #   end\n      def present(*args, root: nil, with: nil, **options)\n        key, object = args.count == 2 && args.first.is_a?(Symbol) ? args : [nil, args.first]\n        entity_class = with || entity_class_for_obj(object)\n        representation = entity_class ? entity_representation_for(entity_class, object, options) : object\n        representation = { root => representation } if root\n\n        if key\n          representation = body&.merge(key => representation) || { key => representation }\n        elsif entity_class.present? && body\n          raise ArgumentError, \"Representation of type #{representation.class} cannot be merged.\" unless representation.respond_to?(:merge)\n\n          representation = body.merge(representation)\n        end\n\n        body representation\n      end\n\n      # Attempt to locate the Entity class for a given object, if not given\n      # explicitly. This is done by looking for the presence of Klass::Entity,\n      # where Klass is the class of the `object` parameter, or one of its\n      # ancestors. Object is excluded from the search: top-level constants\n      # live on it, so a global ::Entity class is not a representer.\n      # @param object [Object] the object to locate the Entity class for\n      # @return [Class] the located Entity class, or nil if none is found\n      def entity_class_for_obj(object)\n        entity_for_class(object.class) || entity_for_class(element_class(object))\n      end\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/ruby-grape/grape/blob/22d7975629846a3c0c7bd2b34e140a7a1b4af8f6/lib/grape/dsl/entity.rb#L19-L55","documentation":"When `present` is called while a response body already exists and an entity class is involved, Grape merges the new representation into the existing body with `merge`. Entities representing a collection produce an Array (or another non-Hash) value, which does not respond to `merge`, so Grape raises 'Representation of type Array cannot be merged.' instead of silently producing a broken body.","triggerScenarios":"Two `present` calls in one endpoint where the later one presents a collection with an entity: `present user, with: UserEntity` followed by `present cars, with: CarEntity` (the second representation is an Array). Presenting any entity whose root-level output is not a Hash when a body is already set.","commonSituations":"Building a compound response (user + their items) by calling present once per section. Returning an array entity after a `present status_message` style call. Migration from single-object endpoints to endpoints that also include collections.","solutions":["Present collections under a key so the wrapper Hash is mergeable: `present :cars, cars, with: CarEntity`.","Use the `root:` option to wrap the representation in a Hash: `present cars, with: CarEntity, root: 'cars'`.","Present a single composite entity for the whole response, or build the response hash manually and present it once."],"exampleFix":"# before\nget '/dashboard' do\n  present user, with: UserEntity\n  present cars, with: CarEntity # Array cannot be merged\nend\n\n# after\nget '/dashboard' do\n  present :user, user, with: UserEntity\n  present :cars, cars, with: CarEntity\nend","handlingStrategy":"validation","validationCode":"# Keyed presents always merge (the wrapper is a Hash), so prefer them for compound bodies\npresent :user, user, with: UserEntity\npresent :cars, cars, with: CarEntity","typeGuard":"# before a second bare present of a collection, check mergeability of the entity output\nrepresentation = CarEntity.represent(cars)\nraise ArgumentError, 'use a key/root for collection entities' unless representation.respond_to?(:merge)","tryCatchPattern":null,"preventionTips":["Adopt the keyed form `present :key, object, with: Entity` for every additional section of a response.","One endpoint, one root entity: model compound responses as a single parent entity.","Spec compound endpoints so a second collection present fails at test time, not at runtime."],"tags":["grape","present","entity","response-body","merge"],"backgroundTag":"non-mergeable-response-body","analyzedSha":"22d7975629846a3c0c7bd2b34e140a7a1b4af8f6","analyzedAt":"2026-08-21T17:03:54.627Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}