{"record":{"id":"29373d8382f76d94","repo":"opf/openproject","slug":"missing-relation-type-parameter","errorCode":null,"errorMessage":"Missing relation_type parameter","messagePattern":"Missing relation_type parameter","errorType":"exception","errorClass":"WorkPackageHierarchyRelationsController::InvalidRelationType","httpStatus":422,"severity":"warning","filePath":"app/controllers/work_package_hierarchy_relations_controller.rb","lineNumber":95,"sourceCode":"\n  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,","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/opf/openproject/blob/d9742c43f3424c34b63550f8c03f201fe5c3040c/app/controllers/work_package_hierarchy_relations_controller.rb#L77-L113","documentation":"WorkPackageHierarchyRelationsController#relation_type reads params[:relation_type] and raises InvalidRelationType('Missing relation_type parameter') when it is blank. The hierarchy tab's create action posts relation_type together with params[:work_package][:id] to express 'make X the parent/child of the current work package'; without the param the direction is undefined and the request is rejected.","triggerScenarios":"POSTing to the work package hierarchy relations endpoint without relation_type — e.g. a custom client replaying the form, a stale JS bundle whose hidden relation_type field was renamed, or a form submission stripped of the field.","commonSituations":"Browser running cached/old assets after an OpenProject upgrade (field renamed or dropped from the payload); third-party automation posting to the endpoint by URL imitation; a copy-pasted form template missing the hidden input.","solutions":["Include relation_type in the request: 'parent' (the related work package becomes parent) or 'child' (it becomes child).","Hard-refresh / clear cached frontend assets so the hierarchy form posts the shipped field set.","For automation, prefer the documented API endpoint for relations instead of replaying the internal form."],"exampleFix":"# before\npost work_package_hierarchy_relations_path(work_package_id: wp.id), params: { work_package: { id: other.id } }\n\n# after\npost work_package_hierarchy_relations_path(work_package_id: wp.id), params: { relation_type: 'child', work_package: { id: other.id } }","handlingStrategy":"validation","validationCode":"raise InvalidRelationType, 'relation_type required' if params[:relation_type].blank?","typeGuard":"def valid_relation_type?(value)\n  value.in?([Relation::TYPE_PARENT, Relation::TYPE_CHILD])\nend","tryCatchPattern":"begin\n  relation_type\nrescue WorkPackageHierarchyRelationsController::InvalidRelationType\n  render json: { error: 'relation_type must be parent or child' }, status: :bad_request\nend","preventionTips":["Make relation_type a required hidden field in the hierarchy form and assert it in request specs.","Cache-bust frontend assets after upgrades so stale forms post the full field set.","For API clients, use the documented relations endpoints rather than replaying internal form payloads."],"tags":["work-packages","hierarchy","relations","parameter-validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"d9742c43f3424c34b63550f8c03f201fe5c3040c","analyzedAt":"2026-08-21T14:40:06.829Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}