diff --git a/app/assets/javascripts/environments/components/environment.js.es6 b/app/assets/javascripts/environments/components/environment.js.es6
index 80384ea8d72b8318dfd723a330c39cdcf5377ab1..6e450df3c41a74e232bab94d59366134539db091 100644
--- a/app/assets/javascripts/environments/components/environment.js.es6
+++ b/app/assets/javascripts/environments/components/environment.js.es6
@@ -193,7 +193,7 @@
 
           <div class="blank-state blank-state-no-icon"
             v-if="!isLoading && state.environments.length === 0">
-            <h2 class="blank-state-title">
+            <h2 class="blank-state-title js-blank-state-title">
               You don't have any environments right now.
             </h2>
             <p class="blank-state-text">
@@ -207,7 +207,7 @@
             <a
               v-if="canCreateEnvironmentParsed"
               :href="newEnvironmentPath"
-              class="btn btn-create">
+              class="btn btn-create js-new-environment-button">
               New Environment
             </a>
           </div>
diff --git a/app/assets/javascripts/environments/stores/environments_store.js.es6 b/app/assets/javascripts/environments/stores/environments_store.js.es6
index 0204a903ab58950241547cb341a7a642c3977280..46e39a15ac9abbc78910e7e735028752b1d14360 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js.es6
+++ b/app/assets/javascripts/environments/stores/environments_store.js.es6
@@ -59,7 +59,7 @@
 
           if (occurs.length) {
             acc[acc.indexOf(occurs[0])].children.push(environment);
-            acc[acc.indexOf(occurs[0])].children.sort(this.sortByName);
+            acc[acc.indexOf(occurs[0])].children.slice().sort(this.sortByName);
           } else {
             acc.push({
               name: environment.environment_type,
@@ -73,7 +73,7 @@
         }
 
         return acc;
-      }, []).sort(this.sortByName);
+      }, []).slice().sort(this.sortByName);
 
       this.state.environments = environmentsTree;
 
diff --git a/changelogs/unreleased/25507-handle-errors-environment-list.yml b/changelogs/unreleased/25507-handle-errors-environment-list.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4e9794f7917da363274812f73473879e1a8401b7
--- /dev/null
+++ b/changelogs/unreleased/25507-handle-errors-environment-list.yml
@@ -0,0 +1,4 @@
+---
+title: Handle HTTP errors in environment list
+merge_request:
+author:
diff --git a/spec/javascripts/environments/environment_spec.js.es6 b/spec/javascripts/environments/environment_spec.js.es6
new file mode 100644
index 0000000000000000000000000000000000000000..20e11ca3738206e86ba38c608e704cd05d40daed
--- /dev/null
+++ b/spec/javascripts/environments/environment_spec.js.es6
@@ -0,0 +1,127 @@
+/* global Vue, environment */
+
+//= require vue
+//= require vue-resource
+//= require flash
+//= require environments/stores/environments_store
+//= require environments/components/environment
+//= require ./mock_data
+
+describe('Environment', () => {
+  preloadFixtures('environments/environments');
+
+  let component;
+
+  beforeEach(() => {
+    loadFixtures('environments/environments');
+  });
+
+  describe('successfull request', () => {
+    describe('without environments', () => {
+      const environmentsEmptyResponseInterceptor = (request, next) => {
+        next(request.respondWith(JSON.stringify([]), {
+          status: 200,
+        }));
+      };
+
+      beforeEach(() => {
+        Vue.http.interceptors.push(environmentsEmptyResponseInterceptor);
+      });
+
+      afterEach(() => {
+        Vue.http.interceptors = _.without(
+          Vue.http.interceptors, environmentsEmptyResponseInterceptor,
+        );
+      });
+
+      it('should render the empty state', (done) => {
+        component = new gl.environmentsList.EnvironmentsComponent({
+          el: document.querySelector('#environments-list-view'),
+          propsData: {
+            store: gl.environmentsList.EnvironmentsStore.create(),
+          },
+        });
+
+        setTimeout(() => {
+          expect(
+            component.$el.querySelector('.js-new-environment-button').textContent,
+          ).toContain('New Environment');
+
+          expect(
+            component.$el.querySelector('.js-blank-state-title').textContent,
+          ).toContain('You don\'t have any environments right now.');
+
+          done();
+        }, 0);
+      });
+    });
+
+    describe('with environments', () => {
+      const environmentsResponseInterceptor = (request, next) => {
+        next(request.respondWith(JSON.stringify([environment]), {
+          status: 200,
+        }));
+      };
+
+      beforeEach(() => {
+        Vue.http.interceptors.push(environmentsResponseInterceptor);
+      });
+
+      afterEach(() => {
+        Vue.http.interceptors = _.without(
+          Vue.http.interceptors, environmentsResponseInterceptor,
+        );
+      });
+
+      it('should render a table with environments', (done) => {
+        component = new gl.environmentsList.EnvironmentsComponent({
+          el: document.querySelector('#environments-list-view'),
+          propsData: {
+            store: gl.environmentsList.EnvironmentsStore.create(),
+          },
+        });
+
+        setTimeout(() => {
+          expect(
+            component.$el.querySelectorAll('table tbody tr').length,
+          ).toEqual(1);
+          done();
+        }, 0);
+      });
+    });
+  });
+
+  describe('unsuccessfull request', () => {
+    const environmentsErrorResponseInterceptor = (request, next) => {
+      next(request.respondWith(JSON.stringify([]), {
+        status: 500,
+      }));
+    };
+
+    beforeEach(() => {
+      Vue.http.interceptors.push(environmentsErrorResponseInterceptor);
+    });
+
+    afterEach(() => {
+      Vue.http.interceptors = _.without(
+        Vue.http.interceptors, environmentsErrorResponseInterceptor,
+      );
+    });
+
+    it('should render empty state', (done) => {
+      component = new gl.environmentsList.EnvironmentsComponent({
+        el: document.querySelector('#environments-list-view'),
+        propsData: {
+          store: gl.environmentsList.EnvironmentsStore.create(),
+        },
+      });
+
+      setTimeout(() => {
+        expect(
+          component.$el.querySelector('.js-blank-state-title').textContent,
+        ).toContain('You don\'t have any environments right now.');
+        done();
+      }, 0);
+    });
+  });
+});
diff --git a/spec/javascripts/environments/mock_data.js.es6 b/spec/javascripts/environments/mock_data.js.es6
index 9e16bc3e6a5f800d715e3a61b833d0a54255d14f..8ecd01f9a832b6581b9bb9b51b194afaac079e8c 100644
--- a/spec/javascripts/environments/mock_data.js.es6
+++ b/spec/javascripts/environments/mock_data.js.es6
@@ -133,3 +133,17 @@ const environmentsList = [
     updated_at: '2016-11-07T11:11:16.525Z',
   },
 ];
+
+const environment = {
+  id: 4,
+  name: 'production',
+  state: 'available',
+  external_url: 'http://production.',
+  environment_type: null,
+  last_deployment: {},
+  'stoppable?': false,
+  environment_path: '/root/review-app/environments/4',
+  stop_path: '/root/review-app/environments/4/stop',
+  created_at: '2016-12-16T11:51:04.690Z',
+  updated_at: '2016-12-16T12:04:51.133Z',
+};
diff --git a/spec/javascripts/fixtures/environments/environments.html.haml b/spec/javascripts/fixtures/environments/environments.html.haml
index d89bc50c1f09fcbc6ae3aaa20da6898074864955..e6000fbb553ab3d0f70b865add513a896bf42501 100644
--- a/spec/javascripts/fixtures/environments/environments.html.haml
+++ b/spec/javascripts/fixtures/environments/environments.html.haml
@@ -1,5 +1,5 @@
 %div
-  #environments-list-view{ data: { environments_data: "https://gitlab.com/foo/environments",
+  #environments-list-view{ data: { environments_data: "foo/environments",
     "can-create-deployment" => "true",
     "can-read-environment" => "true",
     "can-create-environment" => "true",