instructure/canvas-lms · error
can only forward one conversation at a time
Error message
can only forward one conversation at a time
What it means
Conversation#add_message (and forwarding flow) validates forwarded messages come from exactly one conversation. After filtering to forwardable messages, if the resulting distinct conversation_ids count is not 1, this error is raised to prevent mixing messages from multiple conversations in one forward.
Solutions
- Ensure the forwarded message IDs all belong to a single conversation before calling add_message
- Filter the selection in the UI so multi-conversation selections are forwarded in separate calls
- Check messages are forwardable? first; if none are, skip forwarding instead of passing empty/mixed IDs
Example fix
// before conversation.add_message(user, 'fyi', forwarded_message_ids: [1, 2, 77]) // after ids = [1, 2] # all from conversation 42 conversation.add_message(user, 'fyi', forwarded_message_ids: ids) # forward messages from conversation 77 in a separate call
Defensive patterns
Strategy: validation
Validate before calling
ids = forwarded_message_ids.map(&:to_i) convs = ConversationMessage.where(id: ids).select(&:forwardable?).map(&:conversation_id).uniq raise ArgumentError, 'forward messages from exactly one conversation' unless convs.size == 1
Type guard
null
Try / catch
null
Prevention
- Restrict multi-select forwarding in the UI to a single conversation
- Validate message ownership/conversation before queuing forwards
- Handle empty forwardable sets without calling add_message
When it happens
Trigger: Calling Conversation#add_message with options[:forwarded_message_ids] containing messages from more than one conversation, or IDs that resolve to zero forwardable messages (conversation_ids.size == 0).
Common situations: UI code letting users multi-select messages across conversations then forwarding them together; stale/expired message IDs that are no longer forwardable so the filtered set is empty; passing raw arrays of mixed IDs from a client.
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
- user doesn't have permission to forward these messages
- assessor and assessee required
- association required
- can't accept
- can't add participants if there are no messages
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/73f17ac0becfe5f4.
Report an issue: GitHub.
Appendix: source
Thrown at app/models/conversation.rb:355
def self.build_message(current_user, body, options = {})
message = ConversationMessage.new
message.author_id = current_user.id
message.body = body
message.generated = options[:generated] || false
message.automated = options[:automated] || false
if options[:root_account_id]
message.context_type = "Account"
message.context_id = options[:root_account_id]
end
message.asset = options[:asset]
message.attachment_ids = options[:attachment_ids] if options[:attachment_ids].present?
message.media_comment = options[:media_comment] if options[:media_comment].present?
if options[:forwarded_message_ids].present?
messages = ConversationMessage.where(id: options[:forwarded_message_ids].map(&:to_i))
conversation_ids = messages.select(&:forwardable?).map(&:conversation_id).uniq
raise "can only forward one conversation at a time" if conversation_ids.size != 1
raise "user doesn't have permission to forward these messages" unless current_user.all_conversations.where(conversation_id: conversation_ids.first).exists?
# TODO: optimize me
message.forwarded_message_ids = messages.map(&:id).join(",")
end
# Grab snapshot hash of user's inbox settings and save to message (If FF is enabled)
if Account.site_admin.feature_enabled?(:inbox_settings)
message.inbox_settings_ooo_hash = Inbox::InboxService.inbox_settings_ooo_hash(user_id: current_user.id, root_account_id: options[:root_account_id])
end
message
end
def preload_users_and_context_codes
users = User.where(id: conversation_participants.map(&:user_id)).pluck(:id, :updated_at).map do |id, updated_at|
User.send(:instantiate, "id" => id, "updated_at" => updated_at)
endView on GitHub (pinned to 1c9f0bb801)