diff --git a/app/javascript/mastodon/components/error_boundary.js b/app/javascript/mastodon/components/error_boundary.js
new file mode 100644
index 00000000000000..d1ca5bf756a351
--- /dev/null
+++ b/app/javascript/mastodon/components/error_boundary.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import illustration from '../../images/elephant_ui_disappointed.svg';
+
+export default class ErrorBoundary extends React.PureComponent {
+
+ static propTypes = {
+ children: PropTypes.node,
+ };
+
+ state = {
+ hasError: false,
+ stackTrace: undefined,
+ componentStack: undefined,
+ }
+
+ componentDidCatch(error, info) {
+ this.setState({
+ hasError: true,
+ stackTrace: error.stack,
+ componentStack: info && info.componentStack,
+ });
+ }
+
+ render() {
+ const { hasError } = this.state;
+
+ if (!hasError) {
+ return this.props.children;
+ }
+
+ return (
+
+
+
+ );
+ }
+
+}
diff --git a/app/javascript/mastodon/containers/mastodon.js b/app/javascript/mastodon/containers/mastodon.js
index 2912540a00f189..542b682821ee5c 100644
--- a/app/javascript/mastodon/containers/mastodon.js
+++ b/app/javascript/mastodon/containers/mastodon.js
@@ -13,6 +13,7 @@ import { connectUserStream } from '../actions/streaming';
import { IntlProvider, addLocaleData } from 'react-intl';
import { getLocale } from '../locales';
import initialState from '../initial_state';
+import ErrorBoundary from '../components/error_boundary';
const { localeData, messages } = getLocale();
addLocaleData(localeData);
@@ -75,7 +76,9 @@ export default class Mastodon extends React.PureComponent {
return (
-
+
+
+
);
diff --git a/app/javascript/mastodon/features/ui/components/bundle.js b/app/javascript/mastodon/features/ui/components/bundle.js
index e7d93525175c26..a60ace35ba670e 100644
--- a/app/javascript/mastodon/features/ui/components/bundle.js
+++ b/app/javascript/mastodon/features/ui/components/bundle.js
@@ -53,6 +53,11 @@ class Bundle extends React.PureComponent {
const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props;
const cachedMod = Bundle.cache.get(fetchComponent);
+ if (fetchComponent === undefined) {
+ this.setState({ mod: null });
+ return Promise.resolve();
+ }
+
onFetch();
if (cachedMod) {