diff --git a/frontend/src/metabase/visualizations/components/Visualization.jsx b/frontend/src/metabase/visualizations/components/Visualization.jsx
index f336f993a9ce5ee9f22143bf55bbe44ae423d67a..fb9ed971871fa88dda959886480aa224485cfeb7 100644
--- a/frontend/src/metabase/visualizations/components/Visualization.jsx
+++ b/frontend/src/metabase/visualizations/components/Visualization.jsx
@@ -258,7 +258,7 @@ export default class Visualization extends Component {
     }
 
     render() {
-        const { actionButtons, className, showTitle, isDashboard, width, height, errorIcon, isSlow, expectedDuration, replacementContent } = this.props;
+        const { actionButtons, className, showTitle, isDashboard, width, height, isSlow, expectedDuration, replacementContent } = this.props;
         const { series, CardVisualization } = this.state;
         const small = width < 330;
 
@@ -270,6 +270,7 @@ export default class Visualization extends Component {
         }
 
         let error = this.props.error || this.state.error;
+        let errorIcon = this.props.errorIcon || this.state.errorIcon;
         let loading = !(series && series.length > 0 && _.every(series, (s) => s.data));
         let noResults = false;
 
@@ -287,17 +288,22 @@ export default class Visualization extends Component {
                     }
                 } catch (e) {
                     error = e.message || "Could not display this chart with this data.";
-                    if (e instanceof ChartSettingsError && this.props.onOpenChartSettings) {
-                        error = (
-                            <div>
-                                <div>{error}</div>
-                                <div className="mt2">
-                                    <button className="Button Button--primary Button--medium" onClick={this.props.onOpenChartSettings}>
-                                        {e.buttonText}
-                                    </button>
+                    if (e instanceof ChartSettingsError) {
+                        if (this.props.onOpenChartSettings) {
+                            error = (
+                                <div>
+                                    <div>{error}</div>
+                                    <div className="mt2">
+                                        <button className="Button Button--primary Button--medium" onClick={this.props.onOpenChartSettings}>
+                                            {e.buttonText}
+                                        </button>
+                                    </div>
                                 </div>
-                            </div>
-                        );
+                            );
+                        }
+                        if (e.section === "Columns") {
+                            errorIcon = 'empty';
+                        }
                     } else if (e instanceof MinRowsError) {
                         noResults = true;
                     }
diff --git a/frontend/src/metabase/visualizations/visualizations/Table.jsx b/frontend/src/metabase/visualizations/visualizations/Table.jsx
index 7082cc4d2ace129afa74965cc743e9b240f808d5..1a3e4f112ebd4cc6e56a26d4b8c74cc2e61bcf0f 100644
--- a/frontend/src/metabase/visualizations/visualizations/Table.jsx
+++ b/frontend/src/metabase/visualizations/visualizations/Table.jsx
@@ -11,9 +11,9 @@ import Query from "metabase/lib/query";
 import { isMetric, isDimension } from "metabase/lib/schema_metadata";
 import { columnsAreValid, getFriendlyName } from "metabase/visualizations/lib/utils";
 import ChartSettingOrderedFields from "metabase/visualizations/components/settings/ChartSettingOrderedFields.jsx";
-import { MinColumnsError } from "metabase/visualizations/lib/errors";
 
 import _ from "underscore";
+import RetinaImage from "react-retina-image";
 import { getIn } from "icepick";
 
 import type { DatasetData } from "metabase/meta/types/Dataset";
@@ -45,10 +45,6 @@ export default class Table extends Component {
 
     static checkRenderable([{ data: { cols, rows} }], settings) {
         // scalar can always be rendered, nothing needed here
-        const enabledColumns = (settings["table.columns"] || []).filter(f => f.enabled);
-        if (enabledColumns.length < 1) {
-            throw new MinColumnsError(1, enabledColumns.length);
-        }
     }
 
     static settings = {
@@ -130,21 +126,38 @@ export default class Table extends Component {
         const { data } = this.state;
         const sort = getIn(card, ["dataset_query", "query", "order_by"]) || null;
         const isPivoted = settings["table.pivot"];
+        const isColumnsDisabled = (settings["table.columns"] || []).filter(f => f.enabled).length < 1;
         const TableComponent = isDashboard ? TableSimple : TableInteractive;
 
         if (!data) {
             return null;
         }
 
-        return (
-            // $FlowFixMe
-            <TableComponent
-                {...this.props}
-                data={data}
-                isPivoted={isPivoted}
-                sort={sort}
-            />
-        );
+        if (isColumnsDisabled) {
+            return (
+                <div className={"flex-full px1 pb1 text-centered flex flex-column layout-centered " + (isDashboard ? "text-slate-light" : "text-slate")}>
+                    <RetinaImage
+                        width={99}
+                        src="app/assets/img/hidden-field.png"
+                        forceOriginalDimensions={false}
+                        className="mb2"
+                    />
+                    <span className="h4 text-bold">
+                        Every field is hidden right now
+                    </span>
+                </div>
+            )
+        } else {
+            return (
+                // $FlowFixMe
+                <TableComponent
+                    {...this.props}
+                    data={data}
+                    isPivoted={isPivoted}
+                    sort={sort}
+                />
+            );
+        }
     }
 }
 
diff --git a/frontend/test/visualizations/components/Visualization.integ.spec.js b/frontend/test/visualizations/components/Visualization.integ.spec.js
index 275a365fa2ffa92c287d8d6993cf17f0762dfbf3..7b26d15eb74e10153323408676bf593053424d6b 100644
--- a/frontend/test/visualizations/components/Visualization.integ.spec.js
+++ b/frontend/test/visualizations/components/Visualization.integ.spec.js
@@ -2,7 +2,7 @@ import "__support__/integrated_tests";
 
 import React from "react";
 
-import Visualization from "metabase/visualizations/components/Visualization";
+import ChartSettingOrderedFields from "metabase/visualizations/components/Visualization";
 
 import LegendHeader from "metabase/visualizations/components/LegendHeader";
 import LegendItem from "metabase/visualizations/components/LegendItem";
diff --git a/frontend/test/visualizations/components/settings/ChartSettingOrderedFields.unit.spec.js b/frontend/test/visualizations/components/settings/ChartSettingOrderedFields.unit.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..4df304f2f02fda5af4b3437401056de4b85d5ef9
--- /dev/null
+++ b/frontend/test/visualizations/components/settings/ChartSettingOrderedFields.unit.spec.js
@@ -0,0 +1,121 @@
+import "__support__/integrated_tests";
+
+import React from "react";
+
+import ChartSettingOrderedFields from "metabase/visualizations/components/settings/ChartSettingOrderedFields";
+
+import { ScalarCard } from "../__support__/visualizations";
+
+import { mount } from "enzyme";
+
+function renderVisualization(props) {
+    return mount(<ChartSettingOrderedFields className="spread" {...props} />);
+}
+
+function getScalarTitles (scalarComponent) {
+    return scalarComponent.find('.Scalar-title').map((title) => title.text())
+}
+
+function getTitles(viz) {
+    return viz.find(LegendHeader).map(header =>
+        header.find(LegendItem).map((item) => item.props().title)
+    )
+}
+
+describe("Visualization", () => {
+    describe("not in dashboard", () => {
+        describe("scalar card", () => {
+            it("should not render title", () => {
+                let viz = renderVisualization({ series: [ScalarCard("Foo")] });
+                expect(getScalarTitles(viz)).toEqual([]);
+            });
+        });
+
+        describe("line card", () => {
+            it("should not render card title", () => {
+                let viz = renderVisualization({ series: [LineCard("Foo")] });
+                expect(getTitles(viz)).toEqual([]);
+            });
+            it("should not render setting title", () => {
+                let viz = renderVisualization({ series: [LineCard("Foo", { card: { visualization_settings: { "card.title": "Foo_title" }}})] });
+                expect(getTitles(viz)).toEqual([]);
+            });
+            it("should render breakout multiseries titles", () => {
+                let viz = renderVisualization({ series: [MultiseriesLineCard("Foo")] });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_cat1", "Foo_cat2"]
+                ]);
+            });
+        });
+    });
+
+    describe("in dashboard", () => {
+        describe("scalar card", () => {
+            it("should render a scalar title, not a legend title", () => {
+                let viz = renderVisualization({ series: [ScalarCard("Foo")], showTitle: true, isDashboard: true });
+                expect(getTitles(viz)).toEqual([]);
+                expect(getScalarTitles(viz).length).toEqual(1);
+            });
+            it("should render title when loading", () => {
+                let viz = renderVisualization({ series: [ScalarCard("Foo", { data: null })], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name"]
+                ]);
+            });
+            it("should render title when there's an error", () => {
+                let viz = renderVisualization({ series: [ScalarCard("Foo")], showTitle: true, error: "oops" });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name"]
+                ]);
+            });
+            it("should not render scalar title", () => {
+                let viz = renderVisualization({ series: [ScalarCard("Foo")], showTitle: true });
+                expect(getTitles(viz)).toEqual([]);
+            });
+            it("should render multi scalar titles", () => {
+                let viz = renderVisualization({ series: [ScalarCard("Foo"), ScalarCard("Bar")], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name", "Bar_name"]
+                ]);
+            });
+        });
+
+        describe("line card", () => {
+            it("should render normal title", () => {
+                let viz = renderVisualization({ series: [LineCard("Foo")], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name"]
+                ]);
+            });
+            it("should render normal title and breakout multiseries titles", () => {
+                let viz = renderVisualization({ series: [MultiseriesLineCard("Foo")], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name"],
+                    ["Foo_cat1", "Foo_cat2"]
+                ]);
+            });
+            it("should render dashboard multiseries titles", () => {
+                let viz = renderVisualization({ series: [LineCard("Foo"), LineCard("Bar")], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name", "Bar_name"]
+                ]);
+            });
+            it("should render dashboard multiseries titles and chart setting title", () => {
+                let viz = renderVisualization({ series: [
+                    LineCard("Foo", { card: { visualization_settings: { "card.title": "Foo_title" }}}),
+                    LineCard("Bar")
+                ], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_title"],
+                    ["Foo_name", "Bar_name"]
+                ]);
+            });
+            it("should render multiple breakout multiseries titles (with both card titles and breakout values)", () => {
+                let viz = renderVisualization({ series: [MultiseriesLineCard("Foo"), MultiseriesLineCard("Bar")], showTitle: true });
+                expect(getTitles(viz)).toEqual([
+                    ["Foo_name: Foo_cat1", "Foo_name: Foo_cat2", "Bar_name: Bar_cat1", "Bar_name: Bar_cat2"]
+                ]);
+            });
+        });
+    });
+});
diff --git a/resources/frontend_client/app/assets/img/hidden-field.png b/resources/frontend_client/app/assets/img/hidden-field.png
new file mode 100644
index 0000000000000000000000000000000000000000..534b47c4de9a55a5ff6563e43a17e2fac7023339
Binary files /dev/null and b/resources/frontend_client/app/assets/img/hidden-field.png differ
diff --git a/resources/frontend_client/app/assets/img/hidden-field@2x.png b/resources/frontend_client/app/assets/img/hidden-field@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..5fb615c47eb72f0bf27da619014aaa343d90f289
Binary files /dev/null and b/resources/frontend_client/app/assets/img/hidden-field@2x.png differ