instructure/canvas-lms · error · ActiveRecord::RecordNotSaved
Cannot unarchive a deleted LearningOutcome
Error message
Cannot unarchive a deleted LearningOutcome
What it means
LearningOutcome#unarchive! returns an archived outcome to 'active' and clears archived_at. Unarchiving a deleted outcome is an invalid transition, raising ActiveRecord::RecordNotSaved when workflow_state is 'deleted'.
Solutions
- Guard: only call unarchive! when workflow_state == 'archived'.
- Reload the outcome and re-check state before the transition.
- Rescue ActiveRecord::RecordNotSaved and surface 'outcome was deleted' to the user.
- Restore deleted outcomes via the proper deletion-undo path, not unarchive!.
Example fix
// before outcome.unarchive! // after outcome.reload.unarchive! if outcome.reload.workflow_state == "archived"
Defensive patterns
Strategy: try-catch
Validate before calling
outcome.reload.unarchive! if outcome.reload.workflow_state == "archived"
Try / catch
begin outcome.unarchive! rescue ActiveRecord::RecordNotSaved flash[:error] = "This outcome was deleted and cannot be unarchived" end
Prevention
- Check workflow_state before unarchiving
- Reload records before transitions after async deletes
- Restore deleted outcomes via the deletion-undo path, not unarchive!
When it happens
Trigger: Calling outcome.unarchive! on a deleted LearningOutcome — e.g. a stale UI tab or a job operating on a record deleted after load.
Common situations: Outcome deleted while archived; user clicks restore from a stale list; importers toggling states without reloading.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot archive a deleted LearningOutcome
- Cannot archive a deleted LearningOutcomeGroup
- Cannot unarchive a deleted LearningOutcomeGroup
- A course did not pass validation
- A # user did not pass validation (user: # , # : # , error…
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/a29c70967e2a71f7.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/learning_outcome.rb:423
def archive!
# Only active outcomes can be archived
if workflow_state == "active"
self.workflow_state = "archived"
self.archived_at = Time.now.utc
save!
elsif workflow_state == "deleted"
raise ActiveRecord::RecordNotSaved, "Cannot archive a deleted LearningOutcome"
end
end
def unarchive!
# Only archived outcomes can be unarchived
if workflow_state == "archived"
self.workflow_state = "active"
self.archived_at = nil
save!
elsif workflow_state == "deleted"
raise ActiveRecord::RecordNotSaved, "Cannot unarchive a deleted LearningOutcome"
end
end
def assessed?(course = nil)
if course
learning_outcome_results.active.where(context_id: course, context_type: "Course").exists?
elsif learning_outcome_results.active.loaded?
learning_outcome_results.active.any?
else
learning_outcome_results.active.exists?
end
end
def tie_to(context)
@tied_context = context
end
def mastery_pointsView on GitHub (pinned to 1c9f0bb801)