diff --git a/django/contrib/admin/static/admin/js/actions.js b/django/contrib/admin/static/admin/js/actions.js
index 7041701..2d10d06 100644
--- a/django/contrib/admin/static/admin/js/actions.js
+++ b/django/contrib/admin/static/admin/js/actions.js
@@ -113,6 +113,33 @@
             list_editable_changed = true;
         });
         $('form#changelist-form button[name="index"]').click(function(event) {
+            var actionSelected = $('select[name="action"]').val(),
+                itemSelected = $('table#result_list td.action-checkbox input:checked').length > 0,
+                messageList = $('ul.messagelist'),  // admin base.html's message list
+                skipChangeListFormSubmit = function (msg, type, replace) {
+                    event.preventDefault();  // skip submit
+                    if (replace) {
+                        // replace the message list with the new item error
+                        messageList.html('<li class="' + type + '">' + msg + '</li>');
+                    }
+                    else {
+                        // add new item error to the message list
+                        $('<li class="' + type + '">' + msg + '</li>').appendTo(messageList);
+                    }
+                    return;
+                };
+            if (!actionSelected) skipChangeListFormSubmit(
+                gettext("No action selected."),
+                'warning',
+                true
+            );
+            if (!itemSelected) skipChangeListFormSubmit(
+                gettext("Items must be selected in order to perform actions on them. No items have been changed."),
+                'warning',
+                // if `actionSelected` is false, the new item error will be appended to the message list,
+                // keeping the previous item error
+                actionSelected
+            );
             if (list_editable_changed) {
                 return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
             }
diff --git a/django/contrib/admin/static/admin/js/actions.min.js b/django/contrib/admin/static/admin/js/actions.min.js
index c83b06a..eb61fdf 100644
--- a/django/contrib/admin/static/admin/js/actions.min.js
+++ b/django/contrib/admin/static/admin/js/actions.min.js
@@ -1,6 +1,7 @@
-(function(a){var f;a.fn.actions=function(e){var b=a.extend({},a.fn.actions.defaults,e),g=a(this),k=!1,l=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()},m=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()},n=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()},p=function(){n();
-a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)},q=function(c){c?l():n();a(g).prop("checked",c).parent().parent().toggleClass(b.selectedClass,c)},h=function(){var c=a(g).filter(":checked").length,d=a(".action-counter").data("actionsIcnt");a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:d},!0));a(b.allToggle).prop("checked",function(){var a;c===g.length?(a=!0,l()):(a=!1,p());return a})};a(b.counterContainer).show();
-a(this).filter(":checked").each(function(c){a(this).parent().parent().toggleClass(b.selectedClass);h();1===a(b.acrossInput).val()&&m()});a(b.allToggle).show().click(function(){q(a(this).prop("checked"));h()});a("a",b.acrossQuestions).click(function(c){c.preventDefault();a(b.acrossInput).val(1);m()});a("a",b.acrossClears).click(function(c){c.preventDefault();a(b.allToggle).prop("checked",!1);p();q(0);h()});f=null;a(g).click(function(c){c||(c=window.event);var d=c.target?c.target:c.srcElement;if(f&&
-a.data(f)!==a.data(d)&&!0===c.shiftKey){var e=!1;a(f).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked);a(g).each(function(){if(a.data(this)===a.data(f)||a.data(this)===a.data(d))e=e?!1:!0;e&&a(this).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass,d.checked);f=d;h()});a("form#changelist-form table#result_list tr").find("td:gt(0) :input").change(function(){k=!0});a('form#changelist-form button[name="index"]').click(function(a){if(k)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))});
+(function(a){var e;a.fn.actions=function(g){var b=a.extend({},a.fn.actions.defaults,g),f=a(this),k=!1,m=function(){a(b.acrossClears).hide();a(b.acrossQuestions).show();a(b.allContainer).hide()},n=function(){a(b.acrossClears).show();a(b.acrossQuestions).hide();a(b.actionContainer).toggleClass(b.selectedClass);a(b.allContainer).show();a(b.counterContainer).hide()},p=function(){a(b.acrossClears).hide();a(b.acrossQuestions).hide();a(b.allContainer).hide();a(b.counterContainer).show()},q=function(){p();
+a(b.acrossInput).val(0);a(b.actionContainer).removeClass(b.selectedClass)},r=function(c){c?m():p();a(f).prop("checked",c).parent().parent().toggleClass(b.selectedClass,c)},h=function(){var c=a(f).filter(":checked").length,d=a(".action-counter").data("actionsIcnt");a(b.counterContainer).html(interpolate(ngettext("%(sel)s of %(cnt)s selected","%(sel)s of %(cnt)s selected",c),{sel:c,cnt:d},!0));a(b.allToggle).prop("checked",function(){var a;c===f.length?(a=!0,m()):(a=!1,q());return a})};a(b.counterContainer).show();
+a(this).filter(":checked").each(function(c){a(this).parent().parent().toggleClass(b.selectedClass);h();1===a(b.acrossInput).val()&&n()});a(b.allToggle).show().click(function(){r(a(this).prop("checked"));h()});a("a",b.acrossQuestions).click(function(c){c.preventDefault();a(b.acrossInput).val(1);n()});a("a",b.acrossClears).click(function(c){c.preventDefault();a(b.allToggle).prop("checked",!1);q();r(0);h()});e=null;a(f).click(function(c){c||(c=window.event);var d=c.target?c.target:c.srcElement;if(e&&
+a.data(e)!==a.data(d)&&!0===c.shiftKey){var l=!1;a(e).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked);a(f).each(function(){if(a.data(this)===a.data(e)||a.data(this)===a.data(d))l=l?!1:!0;l&&a(this).prop("checked",d.checked).parent().parent().toggleClass(b.selectedClass,d.checked)})}a(d).parent().parent().toggleClass(b.selectedClass,d.checked);e=d;h()});a("form#changelist-form table#result_list tr").find("td:gt(0) :input").change(function(){k=!0});a('form#changelist-form button[name="index"]').click(function(b){var d=
+a('select[name="action"]').val(),e=0<a("table#result_list td.action-checkbox input:checked").length,f=a("ul.messagelist"),g=function(d,e,g){b.preventDefault();g?f.html('<li class="'+e+'">'+d+"</li>"):a('<li class="'+e+'">'+d+"</li>").appendTo(f)};d||g(gettext("No action selected."),"warning",!0);e||g(gettext("Items must be selected in order to perform actions on them. No items have been changed."),"warning",d);if(k)return confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."))});
 a('form#changelist-form input[name="_save"]').click(function(c){var d=!1;a("select option:selected",b.actionContainer).each(function(){a(this).val()&&(d=!0)});if(d)return k?confirm(gettext("You have selected an action, but you haven't saved your changes to individual fields yet. Please click OK to save. You'll need to re-run the action.")):confirm(gettext("You have selected an action, and you haven't made any changes on individual fields. You're probably looking for the Go button rather than the Save button."))})};
 a.fn.actions.defaults={actionContainer:"div.actions",counterContainer:"span.action-counter",allContainer:"div.actions span.all",acrossInput:"div.actions input.select-across",acrossQuestions:"div.actions span.question",acrossClears:"div.actions span.clear",allToggle:"#action-toggle",selectedClass:"selected"};a(document).ready(function(){var e=a("tr input.action-select");0<e.length&&e.actions()})})(django.jQuery);
diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html
index 70e137c..feff6a9 100644
--- a/django/contrib/admin/templates/admin/base.html
+++ b/django/contrib/admin/templates/admin/base.html
@@ -60,11 +60,13 @@
     {% endif %}
 
     {% block messages %}
+        <ul class="messagelist">
         {% if messages %}
-        <ul class="messagelist">{% for message in messages %}
-          <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
-        {% endfor %}</ul>
+            {% for message in messages %}
+              <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message|capfirst }}</li>
+            {% endfor %}
         {% endif %}
+        </ul>
     {% endblock messages %}
 
     <!-- Content -->
