{"record":{"id":"8cd53970434f58d3","repo":"instructure/canvas-lms","slug":"an-outcome-group-can-only-have-one-parent","errorCode":null,"errorMessage":"An outcome group can only have one parent","messagePattern":"An outcome group can only have one parent","errorType":"exception","errorClass":"InvalidDataError","httpStatus":null,"severity":"error","filePath":"lib/outcomes/import.rb","lineNumber":116,"sourceCode":"          raise InvalidDataError, I18n.t(\n            \"Target course %{course_id} is not a child of current account (%{name})\",\n            course_id: group[:course_id],\n            name: context.name\n          )\n        end\n      end\n\n      model = find_prior_group(group, group_context)\n      unless model.context == group_context\n        raise InvalidDataError, I18n.t(\n          \"Group with ID %{guid} already exists in another unrelated course or account (%{name})\",\n          guid: group[:vendor_guid],\n          name: model.context.name\n        )\n      end\n\n      parents = find_parents(group, group_context, model:)\n      raise InvalidDataError, I18n.t(\"An outcome group can only have one parent\") if parents.length > 1\n\n      parent = parents.first\n\n      if model.outcome_import_id == outcome_import_id\n        raise InvalidDataError, I18n.t(\n          'Group \"%{guid}\" has already appeared in this import',\n          guid: group[:vendor_guid]\n        )\n      end\n      model.vendor_guid = group[:vendor_guid]\n      model.title = group[:title]\n      model.description = group[:description] || \"\"\n      model.workflow_state = group[:workflow_state].presence || \"active\"\n      model.learning_outcome_group = parent\n      model.outcome_import_id = outcome_import_id\n      model.save!\n\n      if model.workflow_state == \"deleted\"","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/lib/outcomes/import.rb#L98-L134","documentation":"find_parents resolves the possible parents for the group (from the import's parent/parent_guid fields or the prior group's current parent). A LearningOutcomeGroup has a single learning_outcome_group association, so if resolution yields more than one candidate the import cannot choose and raises this error.","triggerScenarios":"Providing both a parent (canvas id) and parent_guid (vendor guid) on the same group row that resolve to different groups; the group's existing parent plus a new conflicting parent reference in the same import where both match distinct groups.","commonSituations":"CSVs with both legacy parent id columns and newer parent_guid columns filled in inconsistently; hand-edited rows where a stale parent_guid points to a renamed/duplicate group with the same guid in two contexts.","solutions":["Ensure only one parent reference resolves per group — supply either parent id or parent_guid, not conflicting both.","Deduplicate groups that share a vendor_guid in overlapping contexts so guid resolution is unambiguous.","Remove the old parent association before re-parenting in a single import row.","Inspect find_parents to confirm which field it reads and blank the other one."],"exampleFix":"// before\n{ object_type: 'group', parent_id: 10, parent_guid: 'other-parent', ... }\n// after\n{ object_type: 'group', parent_guid: 'other-parent', ... }","handlingStrategy":"validation","validationCode":"if group[:parent_id].present? && group[:parent_guid].present?\n  p1 = LearningOutcomeGroup.find_by(id: group[:parent_id])\n  p2 = LearningOutcomeGroup.find_by(vendor_guid: group[:parent_guid])\n  raise ArgumentError, \"conflicting parents\" unless p1 == p2\nend","typeGuard":null,"tryCatchPattern":"begin\n  importer.import_group(group)\nrescue Outcomes::Import::InvalidDataError => e\n  Rails.logger.warn(\"ambiguous parent for #{group[:vendor_guid]}: #{e.message}\")\nend","preventionTips":["Provide exactly one parent reference per group row","Clean up duplicate vendor_guids so parent_guid resolves uniquely","Decide re-parenting strategy before import, not inside the batch"],"tags":["conflict","ambiguity","hierarchy","outcomes-import"],"backgroundTag":"invalid-argument-value","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}