{"record":{"id":"8ea39d5465b66b91","repo":"opf/openproject","slug":"invalid-relation-type-type","errorCode":null,"errorMessage":"Invalid relation type: #{type}","messagePattern":"Invalid relation type: #(.+?)","errorType":"exception","errorClass":"WorkPackageHierarchyRelationsController::InvalidRelationType","httpStatus":422,"severity":"warning","filePath":"app/controllers/work_package_hierarchy_relations_controller.rb","lineNumber":96,"sourceCode":"  private\n\n  def create_hierarchy_association\n    if related_work_package.id.blank?\n      related_work_package.errors.add(:id, :blank)\n      return ServiceResult.failure(result: related_work_package)\n    end\n\n    if relation_type == \"child\"\n      set_relation(parent: @work_package, child: related_work_package)\n    else\n      set_relation(child: @work_package, parent: related_work_package)\n    end\n  end\n\n  def relation_type\n    type = params[:relation_type]\n    raise InvalidRelationType, \"Missing relation_type parameter\" if type.blank?\n    raise InvalidRelationType, \"Invalid relation type: #{type}\" unless type.in?([Relation::TYPE_PARENT, Relation::TYPE_CHILD])\n\n    type\n  end\n\n  def related_work_package\n    @related_work_package ||=\n      if params[:work_package][:id].present?\n        WorkPackage.visible.find(params[:work_package][:id])\n      else\n        WorkPackage.new\n      end\n  end\n\n  def set_relation(child:, parent:)\n    if allowed_to_set_parent?(child)\n      WorkPackages::UpdateService.new(\n        user: current_user,\n        model: child,","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/opf/openproject/blob/d9742c43f3424c34b63550f8c03f201fe5c3040c/app/controllers/work_package_hierarchy_relations_controller.rb#L78-L114","documentation":"WorkPackageHierarchyRelationsController#relation_type only accepts the two hierarchy values Relation::TYPE_PARENT ('parent') and Relation::TYPE_CHILD ('child'); anything non-blank outside that set raises InvalidRelationType('Invalid relation type: #{type}'). This endpoint models the parent/child tree only — temporal/social relation kinds are rejected here.","triggerScenarios":"Posting relation_type='follows', 'blocks', 'precedes' etc. to the hierarchy relations endpoint — those belong to the general relations API, not the parent/child hierarchy endpoint; also custom strings or typos like 'Parent' (case-sensitive).","commonSituations":"Developers reuse one relations client for all relation kinds and route hierarchy types to the wrong endpoint; case mismatches ('Parent' vs 'parent'); older docs or snippets referencing an accepted set that later got narrowed.","solutions":["Send exactly 'parent' or 'child' (lowercase) to this endpoint.","Use the standard work package relations endpoint for all other relation types (follows, blocks, ...).","Validate the value client-side against ['parent', 'child'] before submitting."],"exampleFix":"# before\npost path, params: { relation_type: 'follows', work_package: { id: other.id } }\n\n# after\npost path, params: { relation_type: 'child', work_package: { id: other.id } }\n# 'follows' belongs to the general relations API instead","handlingStrategy":"validation","validationCode":"type = params[:relation_type].to_s\ntype = type.downcase\nraise InvalidRelationType, type unless type.in?(%w[parent child])","typeGuard":"def hierarchy_relation_type?(value)\n  value.is_a?(String) && value.in?([Relation::TYPE_PARENT, Relation::TYPE_CHILD])\nend","tryCatchPattern":"begin\n  relation_type\nrescue WorkPackageHierarchyRelationsController::InvalidRelationType => e\n  render_error e.message, status: :unprocessable_entity\nend","preventionTips":["Route non-hierarchy relation kinds (follows, blocks, precedes) to the general relations API by design.","Normalize case before validating; document the endpoint's accepted set as exactly parent/child.","Cover both invalid-type and missing-param cases in controller specs to lock the contract."],"tags":["work-packages","hierarchy","relations","parameter-validation"],"backgroundTag":"invalid-parameter-value","analyzedSha":"d9742c43f3424c34b63550f8c03f201fe5c3040c","analyzedAt":"2026-08-21T14:40:06.829Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}