{"record":{"id":"ffd8a3bbddd3ecbe","repo":"instructure/canvas-lms","slug":"unable-to-create-message-without-a-body","errorCode":null,"errorMessage":"Unable to create message without a body","messagePattern":"Unable to create message without a body","errorType":"exception","errorClass":"ConversationsHelper::Error","httpStatus":400,"severity":"error","filePath":"app/helpers/conversations_helper.rb","lineNumber":45,"sourceCode":"    context_code:,\n    message_ids:,\n    body:,\n    attachment_ids:,\n    domain_root_account_id:,\n    media_comment_id:,\n    media_comment_type:,\n    automated: false\n  )\n    if conversation.conversation.replies_locked_for?(current_user, recipients)\n      raise ConversationsHelper::RepliesLockedForUser.new(message: I18n.t(\"Unauthorized, unable to add messages to conversation\"), status: :unauthorized, attribute: \"workflow_state\")\n    end\n\n    if context.is_a?(Course) && context.workflow_state == \"completed\" && !context.grants_right?(current_user, session, :read_as_admin)\n      raise ConversationsHelper::Error.new(message: I18n.t(\"Course concluded, unable to send messages\"), status: :unauthorized, attribute: \"workflow_state\")\n    end\n\n    if body.blank?\n      raise ConversationsHelper::Error.new(message: I18n.t(\"Unable to create message without a body\"), status: :bad_request, attribute: \"empty_message\")\n    end\n\n    recipients = normalize_recipients(\n      recipients:,\n      context_code:,\n      conversation_id: conversation.conversation_id,\n      current_user:,\n      session:\n    )\n\n    if recipients && !conversation.conversation.can_add_participants?(recipients)\n      raise ConversationsHelper::Error.new(message: I18n.t(\"Too many participants for group conversation\"), status: :bad_request, attribute: \"recipients\")\n    end\n\n    invalid_recipients = get_invalid_recipients(context, recipients, current_user)\n    unless invalid_recipients.to_a.empty?\n      invalid_recipients = invalid_recipients.pluck(1)\n      raise ConversationsHelper::Error.new(message: I18n.t(\"The following recipients have no active enrollment in the course, %{invalid_recipients}, unable to send messages\", invalid_recipients:), status: :unauthorized, attribute: \"recipients\")","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/helpers/conversations_helper.rb#L27-L63","documentation":"process_response requires a non-blank message body before creating the message; a blank body raises ConversationsHelper::Error with status :bad_request and attribute 'empty_message'. This prevents empty conversation entries from being created.","triggerScenarios":"Calling process_response (directly or via trigger_out_of_office_auto_responses) with body set to nil, \"\", or whitespace-only text.","commonSituations":"A client submitting an empty composer; an automation assembling a message from a template that rendered empty; stripped HTML leaving nothing after sanitization.","solutions":["Ensure body is non-blank before calling — validate on the client and server","Rescue ConversationsHelper::Error with status :bad_request and re-prompt the user for content","If automation, guard: skip sending when the generated body is blank","Trim/normalize the body and fall back to a sensible default text if appropriate"],"exampleFix":"// before\nadd_message(conversation, body: nil, ...)\n// after\nadd_message(conversation, body: body.presence || 'No message content provided', ...)","handlingStrategy":"validation","validationCode":"return render json: { error: 'body required' }, status: :bad_request if body.blank?","typeGuard":null,"tryCatchPattern":"begin\n  process_response(...)\nrescue ConversationsHelper::Error => e\n  if e.message.include?('without a body')\n    render json: { error: 'message body required' }, status: :bad_request\n  else\n    raise\n  end\nend","preventionTips":["Require the composer to be non-empty client-side","Use body.presence or default text for automated messages","Server-side validate params[:body] in the controller"],"tags":["conversations","validation","empty-input"],"backgroundTag":"empty-required-field","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"}