forem/forem · warning · ArgumentError

Please choose a badge to award

Error message

Please choose a badge to award

What it means

Raised as ArgumentError by Admin::BadgeAchievementsController#award_badges when params[:badge] is blank — the bulk badge-award form was submitted without selecting a badge. The guard runs before usernames are parsed, so no BadgeAchievements::BadgeAwardWorker job is enqueued and no achievements are created.

Source

Thrown at app/controllers/admin/badge_achievements_controller.rb:30

    end

    def destroy
      @badge_achievement = BadgeAchievement.find(params[:id])

      if @badge_achievement.destroy
        render json: { message: I18n.t("admin.badge_achievements_controller.deleted") }, status: :ok
      else
        render json: { error: "Something went wrong." }, status: :unprocessable_entity
      end
    end

    def award
      @all_badges = Badge.select(:title, :slug).order(title: :asc)
    end

    def award_badges
      if permitted_params[:badge].blank?
        raise ArgumentError,
              I18n.t("admin.badge_achievements_controller.award")
      end

      usernames = permitted_params[:usernames].downcase.split(/\s*,\s*/)
      include_default_description = permitted_params[:include_default_description] == "1"
      message = permitted_params[:message_markdown].presence ||
        I18n.t("admin.badge_achievements_controller.congrats", community: ::Settings::Community.community_name)
      BadgeAchievements::BadgeAwardWorker
        .perform_async(usernames,
                       permitted_params[:badge],
                       message,
                       include_default_description)

      flash[:success] = I18n.t("admin.badge_achievements_controller.rewarded")
      redirect_to admin_badge_achievements_path
    rescue ArgumentError => e
      flash[:danger] = e.message
      redirect_to admin_badge_achievements_path

View on GitHub (pinned to f354c376a7)

Solutions

  1. Return to /admin/badge_achievements/award and pick a badge from the select before submitting
  2. Add required: true to the badge select markup so the browser blocks blank submits
  3. If the select is empty, create Badge records first via /admin/badges
  4. For automation, include the badge identifier in the badge field and verify field names against the current form

Example fix

# before (admin view)
<%= f.select :badge, @all_badges.map { |b| [b.title, b.slug] } %>

# after
<%= f.select :badge, @all_badges.map { |b| [b.title, b.slug] }, { prompt: 'Select a badge' }, required: true %>
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: block the submit instead of eating a server ArgumentError
const badge = form.querySelector('[name="badge"]').value;
if (!badge) {
  showToast('Please choose a badge to award');
  return; // do not POST
}
form.submit();

Try / catch

begin
  post :award_badges, params: payload
rescue ArgumentError => e
  flash.now[:error] = e.message # 'Please choose a badge to award'
  render :award, status: :unprocessable_entity
end

Prevention

When it happens

Trigger: POST /admin/badge_achievements/award_badges with the badge field missing or empty: submitting the award form before touching the badge select; a scripted POST omitting the badge key; the select rendering empty because no Badge records exist on the instance.

Common situations: Admin types usernames and hits submit with the select untouched; browser autofill clobbers the select; fresh Forem install with zero badges defined; automated tooling built against an older field name.

Related errors


AI-assisted analysis of forem/forem@f354c376a7 (2026-08-21). Data as JSON: /api/errors/4f3e53912bf93f8a. Report an issue: GitHub.