instructure/canvas-lms · error · ConversationsHelper::Error

not for this conversation

Error message

not for this conversation

What it means

Rescue translator: when building a conversation message, an included_message id that does not belong to the target conversation raises ConversationsHelper::InvalidMessageForConversationError, which is re-raised as a bad_request ConversationsHelper::Error with message 'not for this conversation'.

Solutions

  1. Only pass included_messages ids that appear under the same conversation_id.
  2. Re-fetch the conversation's messages and rebuild the included_messages list before the call.
  3. Catch ConversationsHelper::Error with attribute included_messages and prompt the user to reselect attachments.
  4. Verify message ids via the conversation messages endpoint before attaching.

Example fix

// before
included_messages: [123, 456] // 456 belongs to another conversation
// after
included_messages: conversation.conversation_messages.where(id: [123,456]).pluck(:id)
Defensive patterns

Strategy: validation

Validate before calling

msg_ids = conversation.conversation_messages.pluck(:id)
bad = params[:included_messages] - msg_ids.map(&:to_i)
raise ArgumentError, 'included_messages not in conversation' if bad.any?

Try / catch

begin
  add_message(...)
rescue ConversationsHelper::Error => e
  return render json: { error: e.message, attribute: 'included_messages' }, status: :bad_request
end

Prevention

When it happens

Trigger: Conversations API call passing included_messages[] referencing message ids whose conversation_id differs from the conversation being replied to (e.g. forwarding/multimedia attach with stale or mixed ids).

Common situations: Client merges messages from two threads; UI caches message ids after the conversation was deleted/merged; id typo from manual API testing.

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


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/1d0ebfe5a4029d73. Report an issue: GitHub.

Appendix: source

Thrown at app/helpers/conversations_helper.rb:142

        message = Conversation.build_message(*message_args)
        message.id = 0
        message.conversation_id = conversation.conversation_id
        message.created_at = Time.now.utc
        { message:, recipients_count: existing_participant_ids.size, status: :accepted }
      end
    elsif conversation.should_process_immediately?
      message = conversation.process_new_message(message_args, recipients, message_ids, tags)
      { message:, recipients_count: recipients ? recipients.count : 0, status: :ok }
    else
      conversation.delay(strand: "add_message_#{conversation.global_conversation_id}").process_new_message(message_args, recipients, message_ids, tags)
      message = Conversation.build_message(*message_args)
      message.id = 0
      message.conversation_id = conversation.conversation_id
      message.created_at = Time.now.utc
      { message:, recipients_count: recipients ? recipients.count : 0, status: :accepted }
    end
  rescue ConversationsHelper::InvalidMessageForConversationError
    raise ConversationsHelper::Error.new(message: I18n.t("not for this conversation"), status: :bad_request, attribute: "included_messages")
  rescue ConversationsHelper::InvalidMessageParticipantError
    raise ConversationsHelper::Error.new(message: I18n.t("not a participant"), status: :bad_request, attribute: "included_messages")
  end

  def contexts_for(audience, context_tags)
    result = { courses: {}, groups: {} }
    return result if audience.empty?

    context_tags.each do |tag|
      next unless tag =~ /\A(course|group)_(\d+)\z/

      result[:"#{$1}s"][$2.to_i] = []
    end

    if audience.size == 1 && include_private_conversation_enrollments
      enrollments = Shard.partition_by_shard(result[:courses].keys) do |course_ids|
        next unless audience.first.associated_shards.include?(Shard.current)

View on GitHub (pinned to 1c9f0bb801)