diff --git a/AUTHORS b/AUTHORS
index 90fd6fa310..7a249da5bf 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -474,6 +474,7 @@ answer newbie questions, and generally made Django that much better:
     Luciano Ramalho
     Amit Ramon <amit.ramon@gmail.com>
     Philippe Raoult <philippe.raoult@n2nsoft.com>
+    Senko Rašić <senko.rasic@dobarkod.hr>
     Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
     Brian Ray <http://brianray.chipy.org/>
     Lee Reilly <lee@leereilly.net>
diff --git a/django/forms/formsets.py b/django/forms/formsets.py
index d421770093..3ec94d20ec 100644
--- a/django/forms/formsets.py
+++ b/django/forms/formsets.py
@@ -250,9 +250,9 @@ class BaseFormSet(object):
         form -- i.e., from formset.clean(). Returns an empty ErrorList if there
         are none.
         """
-        if self._non_form_errors is not None:
-            return self._non_form_errors
-        return self.error_class()
+        if self._non_form_errors is None:
+            self.full_clean()
+        return self._non_form_errors
 
     @property
     def errors(self):
@@ -291,9 +291,12 @@ class BaseFormSet(object):
 
     def full_clean(self):
         """
-        Cleans all of self.data and populates self._errors.
+        Cleans all of self.data and populates self._errors and
+        self._non_form_errors.
         """
         self._errors = []
+        self._non_form_errors = self.error_class()
+
         if not self.is_bound: # Stop further processing.
             return
         for i in range(0, self.total_form_count()):
diff --git a/tests/forms_tests/tests/test_formsets.py b/tests/forms_tests/tests/test_formsets.py
index 4ac3c5ecf1..31adb921ba 100644
--- a/tests/forms_tests/tests/test_formsets.py
+++ b/tests/forms_tests/tests/test_formsets.py
@@ -972,6 +972,20 @@ class FormsFormsetTestCase(TestCase):
         finally:
             formsets.DEFAULT_MAX_NUM = _old_DEFAULT_MAX_NUM
 
+    def test_non_form_errors_run_full_clean(self):
+        # Regression test for #11160
+        # If non_form_errors() is called without calling is_valid() first,
+        # it should ensure that full_clean() is called.
+        class BaseCustomFormSet(BaseFormSet):
+            def clean(self):
+                raise ValidationError("This is a non-form error")
+
+        ChoiceFormSet = formset_factory(Choice, formset=BaseCustomFormSet)
+        formset = ChoiceFormSet(data, auto_id=False, prefix='choices')
+        self.assertTrue(isinstance(formset.non_form_errors(), ErrorList))
+        self.assertEqual(list(formset.non_form_errors()),
+            ['This is a non-form error'])
+
 
 data = {
     'choices-TOTAL_FORMS': '1', # the number of forms rendered