instructure/canvas-lms · error · InvalidDataError
An outcome group can only have one parent
Error message
An outcome group can only have one parent
What it means
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.
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.
Example fix
// before
{ object_type: 'group', parent_id: 10, parent_guid: 'other-parent', ... }
// after
{ object_type: 'group', parent_guid: 'other-parent', ... } Defensive patterns
Strategy: validation
Validate before calling
if group[:parent_id].present? && group[:parent_guid].present? p1 = LearningOutcomeGroup.find_by(id: group[:parent_id]) p2 = LearningOutcomeGroup.find_by(vendor_guid: group[:parent_guid]) raise ArgumentError, "conflicting parents" unless p1 == p2 end
Try / catch
begin
importer.import_group(group)
rescue Outcomes::Import::InvalidDataError => e
Rails.logger.warn("ambiguous parent for #{group[:vendor_guid]}: #{e.message}")
end Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Group " " has already appeared in this import
- Group with ID already exists in another unrelated course or…
- Target course is not a child of current account ( )
- A new_id, '# ', referenced an existing # and the # with #…
- A new_integration_id, '#
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/8cd53970434f58d3.
Report an issue: GitHub.
Appendix: source
Thrown at lib/outcomes/import.rb:116
raise InvalidDataError, I18n.t(
"Target course %{course_id} is not a child of current account (%{name})",
course_id: group[:course_id],
name: context.name
)
end
end
model = find_prior_group(group, group_context)
unless model.context == group_context
raise InvalidDataError, I18n.t(
"Group with ID %{guid} already exists in another unrelated course or account (%{name})",
guid: group[:vendor_guid],
name: model.context.name
)
end
parents = find_parents(group, group_context, model:)
raise InvalidDataError, I18n.t("An outcome group can only have one parent") if parents.length > 1
parent = parents.first
if model.outcome_import_id == outcome_import_id
raise InvalidDataError, I18n.t(
'Group "%{guid}" has already appeared in this import',
guid: group[:vendor_guid]
)
end
model.vendor_guid = group[:vendor_guid]
model.title = group[:title]
model.description = group[:description] || ""
model.workflow_state = group[:workflow_state].presence || "active"
model.learning_outcome_group = parent
model.outcome_import_id = outcome_import_id
model.save!
if model.workflow_state == "deleted"View on GitHub (pinned to 1c9f0bb801)