diff --git a/package-lock.json b/package-lock.json
index 9ed115ca86895b2ba30e12139cb0759123fb57f2..a90fe5ad8da5ef157ebe2100cb1abd057eee2bf8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7484,9 +7484,9 @@
       }
     },
     "eslint-config-scratch": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-scratch/-/eslint-config-scratch-5.1.0.tgz",
-      "integrity": "sha512-JQMxERL3eo0TMy87NZFm6yS0i2XOMplffKz9CD/2ta2i/+3FTgajxzF9n7R7vi9C+GMLSTSLZJ5X90tINuAhjg==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-scratch/-/eslint-config-scratch-6.0.0.tgz",
+      "integrity": "sha512-2aW7EVWhjTrwaM54hjAZeRETh/habWeQ5xzTbPO2dG//RtixBztUAmdxqAHKH8MEtmAMsUhf3mRjO1BstO4dGg==",
       "dev": true,
       "requires": {
         "eslint-plugin-react": ">=7.14.2"
diff --git a/package.json b/package.json
index 1d26175122f78084389f36faf20be687aa2c05ce..89049dfaded92e54d9ca1af49fd5b186094ed586 100644
--- a/package.json
+++ b/package.json
@@ -106,8 +106,8 @@
     "chromedriver": "87.0.7",
     "enzyme": "^3.5.0",
     "enzyme-adapter-react-16": "1.3.0",
-    "eslint": "^5.0.1",
-    "eslint-config-scratch": "^5.0.0",
+    "eslint": "^5.7.0",
+    "eslint-config-scratch": "^6.0.0",
     "eslint-import-resolver-webpack": "^0.11.1",
     "eslint-plugin-import": "^2.18.2",
     "eslint-plugin-jest": "^22.14.1",
diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx
index f5d52388ff336680fbdce501f1fcc14821b9d169..fee9d26f7b7a1cf928f61fd08d19344c4f7dd3ba 100644
--- a/src/containers/blocks.jsx
+++ b/src/containers/blocks.jsx
@@ -34,8 +34,8 @@ import {
 
 const addFunctionListener = (object, property, callback) => {
     const oldFn = object[property];
-    object[property] = function () {
-        const result = oldFn.apply(this, arguments);
+    object[property] = function (...args) {
+        const result = oldFn.apply(this, args);
         callback.apply(this, result);
         return result;
     };
diff --git a/src/containers/sound-editor.jsx b/src/containers/sound-editor.jsx
index b8a685a4415454b418646ce7ded95a842738fe33..c81485d0fa095795842966a92d7a2ed1f6210ab9 100644
--- a/src/containers/sound-editor.jsx
+++ b/src/containers/sound-editor.jsx
@@ -165,7 +165,7 @@ class SoundEditor extends React.Component {
             )
             .catch(e => {
                 // Encoding failed, or the sound was too large to save so edit is rejected
-                log.error(`Encountered error while trying to encode sound update: ${e}`);
+                log.error(`Encountered error while trying to encode sound update: ${e.message}`);
                 return false; // Edit was not applied
             });
     }
@@ -349,7 +349,7 @@ class SoundEditor extends React.Component {
                 if (newRate === buffer.sampleRate / 2) {
                     return resolve(dropEveryOtherSample(buffer));
                 }
-                return reject('Could not resample');
+                return reject(new Error('Could not resample'));
             }
             const source = offlineContext.createBufferSource();
             const audioBuffer = offlineContext.createBuffer(1, buffer.samples.length, buffer.sampleRate);
diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx
index 8e1ac9248396c3faa44f20b8eb50fe0e3066e888..bbc942634d693dd76879b8298f9ab9b8cf6c709c 100644
--- a/src/containers/stage.jsx
+++ b/src/containers/stage.jsx
@@ -8,8 +8,7 @@ import {connect} from 'react-redux';
 import {STAGE_DISPLAY_SIZES} from '../lib/layout-constants';
 import {getEventXY} from '../lib/touch-utils';
 import VideoProvider from '../lib/video/video-provider';
-import {SVGRenderer as V2SVGAdapter} from 'scratch-svg-renderer';
-import {BitmapAdapter as V2BitmapAdapter} from 'scratch-svg-renderer';
+import {SVGRenderer as V2SVGAdapter, BitmapAdapter as V2BitmapAdapter} from 'scratch-svg-renderer';
 
 import StageComponent from '../components/stage/stage.jsx';
 
diff --git a/src/lib/audio/audio-util.js b/src/lib/audio/audio-util.js
index 5e53b29377ecb5225af7b97a604febb415d27ccb..bca00fdd108ab75b67afbb2c66bff5571e4a0218 100644
--- a/src/lib/audio/audio-util.js
+++ b/src/lib/audio/audio-util.js
@@ -86,7 +86,7 @@ const downsampleIfNeeded = (buffer, resampler) => {
     }
     // Cannot save this sound at 22khz, refuse to edit
     // In the future we could introduce further compression here
-    return Promise.reject('Sound too large to save, refusing to edit');
+    return Promise.reject(new Error('Sound too large to save, refusing to edit'));
 };
 
 /**
diff --git a/src/lib/backpack-api.js b/src/lib/backpack-api.js
index 550d37d43d6bebfc7c329b4c49f62f38e2ad3490..37a0aded036612ed53ac4955edb63701c22a9b60 100644
--- a/src/lib/backpack-api.js
+++ b/src/lib/backpack-api.js
@@ -26,7 +26,7 @@ const getBackpackContents = ({
         json: true
     }, (error, response) => {
         if (error || response.statusCode !== 200) {
-            return reject();
+            return reject(new Error(response.status));
         }
         return resolve(response.body.map(item => includeFullUrls(item, host)));
     });
@@ -49,7 +49,7 @@ const saveBackpackObject = ({
         json: {type, mime, name, body, thumbnail}
     }, (error, response) => {
         if (error || response.statusCode !== 200) {
-            return reject();
+            return reject(new Error(response.status));
         }
         return resolve(includeFullUrls(response.body, host));
     });
@@ -67,7 +67,7 @@ const deleteBackpackObject = ({
         headers: {'x-token': token}
     }, (error, response) => {
         if (error || response.statusCode !== 200) {
-            return reject();
+            return reject(new Error(response.status));
         }
         return resolve(response.body);
     });
@@ -78,7 +78,7 @@ const deleteBackpackObject = ({
 const fetchAs = (responseType, uri) => new Promise((resolve, reject) => {
     xhr({uri, responseType}, (error, response) => {
         if (error || response.statusCode !== 200) {
-            return reject();
+            return reject(new Error(response.status));
         }
         return resolve(response.body);
     });
diff --git a/src/lib/libraries/.eslintrc.js b/src/lib/libraries/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..25cdd21176ceafd2c9e43f676776a276c0761aef
--- /dev/null
+++ b/src/lib/libraries/.eslintrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+    rules: {
+        // These manifest files use duplicate imports to make things easier to follow
+        // by providing clear parallel structure. Turn the error off for this folder.
+        'no-duplicate-imports': 0
+    }
+};
diff --git a/src/reducers/alerts.js b/src/reducers/alerts.js
index 480c8b3824c954b5bb17cda7335b6155b4b0b3d2..eee72682246e18b234a3ddaf42da73a02df987f9 100644
--- a/src/reducers/alerts.js
+++ b/src/reducers/alerts.js
@@ -1,5 +1,4 @@
-import alertsData from '../lib/alerts/index.jsx';
-import {AlertTypes, AlertLevels} from '../lib/alerts/index.jsx';
+import alertsData, {AlertTypes, AlertLevels} from '../lib/alerts/index.jsx';
 import extensionData from '../lib/libraries/extensions/index.jsx';
 
 const SHOW_ALERT = 'scratch-gui/alerts/SHOW_ALERT';
diff --git a/src/reducers/locales.js b/src/reducers/locales.js
index 34a42163eda0a869133e76bd8f3fa37d6e1de140..84c9b1f080f5b5aef9e8c5eec343ecbb11b0dfc5 100644
--- a/src/reducers/locales.js
+++ b/src/reducers/locales.js
@@ -1,8 +1,7 @@
 import {addLocaleData} from 'react-intl';
 
-import {localeData} from 'scratch-l10n';
+import {localeData, isRtl} from 'scratch-l10n';
 import editorMessages from 'scratch-l10n/locales/editor-msgs';
-import {isRtl} from 'scratch-l10n';
 
 addLocaleData(localeData);
 
diff --git a/test/smoke/browser.test.js b/test/smoke/browser.test.js
index 941b3eef3bd7e34b0165c2002898d4b170fc4b73..2eeb2cfccea46f9c1d9c3f2f91837f2f55cf3bcb 100644
--- a/test/smoke/browser.test.js
+++ b/test/smoke/browser.test.js
@@ -16,7 +16,9 @@ const UNSUPPORTED_MESSAGE = 'Scratch 3.0 does not support Internet Explorer';
 describe('Smoke tests on older browsers', () => {
     let driver;
 
-    afterEach(async () => await (driver && driver.quit()));
+    afterEach(async () => {
+        if (driver) await driver.quit();
+    });
 
     test('Credentials should be provided', () => {
         expect(SAUCE_USERNAME && SAUCE_ACCESS_KEY && SMOKE_URL).toBeTruthy();
diff --git a/test/unit/reducers/alerts-reducer.test.js b/test/unit/reducers/alerts-reducer.test.js
index a34dc86862dc4018025803c88f0cae2d024a41d3..8048d5aef6e9292c072e7b5d07b8448c4e5cc611 100644
--- a/test/unit/reducers/alerts-reducer.test.js
+++ b/test/unit/reducers/alerts-reducer.test.js
@@ -2,8 +2,7 @@
 
 /* eslint-env jest */
 import {AlertTypes, AlertLevels} from '../../../src/lib/alerts/index.jsx';
-import alertsReducer from '../../../src/reducers/alerts';
-import {
+import alertsReducer, {
     closeAlert,
     closeAlertWithId,
     filterInlineAlerts,
diff --git a/test/unit/reducers/monitor-layout-reducer.test.js b/test/unit/reducers/monitor-layout-reducer.test.js
index ea45b20e47eceb7a1c4969fbfe1061cdb5d80d66..8aa01266c5ab2ad08f46e9553b1e17d83ac8912b 100644
--- a/test/unit/reducers/monitor-layout-reducer.test.js
+++ b/test/unit/reducers/monitor-layout-reducer.test.js
@@ -1,8 +1,9 @@
 /* eslint-env jest */
-import monitorLayoutReducer from '../../../src/reducers/monitor-layout';
-import {addMonitorRect, moveMonitorRect} from '../../../src/reducers/monitor-layout';
-import {resizeMonitorRect, removeMonitorRect} from '../../../src/reducers/monitor-layout';
-import {getInitialPosition, PADDING, SCREEN_WIDTH, SCREEN_HEIGHT} from '../../../src/reducers/monitor-layout';
+import monitorLayoutReducer, {
+    addMonitorRect, moveMonitorRect,
+    resizeMonitorRect, removeMonitorRect,
+    getInitialPosition, PADDING, SCREEN_WIDTH, SCREEN_HEIGHT
+} from '../../../src/reducers/monitor-layout';
 
 test('initialState', () => {
     let defaultState;
diff --git a/test/unit/reducers/project-state-reducer.test.js b/test/unit/reducers/project-state-reducer.test.js
index faf208bf4341b8114df38fd8e6543ecb430b8724..8aabc107244bc58574ed1334696cd3a963f7cf7f 100644
--- a/test/unit/reducers/project-state-reducer.test.js
+++ b/test/unit/reducers/project-state-reducer.test.js
@@ -1,6 +1,5 @@
 /* eslint-env jest */
-import projectStateReducer from '../../../src/reducers/project-state';
-import {
+import projectStateReducer, {
     LoadingState,
     autoUpdateProject,
     doneCreatingProject,
diff --git a/test/unit/util/audio-util.test.js b/test/unit/util/audio-util.test.js
index b962dcc53ea15946ef2eecf6b0df9f3d9917502d..7cbcd4058ea03bc73c1a60e709554f02b3f9e4ba 100644
--- a/test/unit/util/audio-util.test.js
+++ b/test/unit/util/audio-util.test.js
@@ -76,7 +76,7 @@ describe('downsampleIfNeeded', () => {
         try {
             await downsampleIfNeeded({samples, sampleRate}, null);
         } catch (e) {
-            expect(e).toEqual('Sound too large to save, refusing to edit');
+            expect(e.message).toEqual('Sound too large to save, refusing to edit');
         }
     });
 });