diff --git a/frontend/src/metabase/meta/types/Visualization.js b/frontend/src/metabase/meta/types/Visualization.js
index dbbb7b7bd342fe707974d03bbf5866ee3beb92ec..fcef2b11f25d13aaa5ce375f9d47b99c3cc3ef8d 100644
--- a/frontend/src/metabase/meta/types/Visualization.js
+++ b/frontend/src/metabase/meta/types/Visualization.js
@@ -113,4 +113,6 @@ export type VisualizationProps = {
   onAddSeries?: Function,
   onEditSeries?: Function,
   onRemoveSeries?: Function,
+
+  onUpdateWarnings?: Function,
 };
diff --git a/frontend/src/metabase/visualizations/components/PinMap.jsx b/frontend/src/metabase/visualizations/components/PinMap.jsx
index df5c77e945eac9f1c7a3b6582927f3de6d3a5c18..72a22c859658d71eb35e00a579c7ad29fd37dc5d 100644
--- a/frontend/src/metabase/visualizations/components/PinMap.jsx
+++ b/frontend/src/metabase/visualizations/components/PinMap.jsx
@@ -126,6 +126,7 @@ export default class PinMap extends Component {
           data: { cols, rows },
         },
       ],
+      onUpdateWarnings,
     } = props;
     const latitudeIndex = _.findIndex(
       cols,
@@ -140,12 +141,27 @@ export default class PinMap extends Component {
       col => col.name === settings["map.metric_column"],
     );
 
-    const points = rows.map(row => [
+    const allPoints = rows.map(row => [
       row[latitudeIndex],
       row[longitudeIndex],
       metricIndex >= 0 ? row[metricIndex] : 1,
     ]);
 
+    // only use points with numeric coordinates & metric
+    const points = allPoints.filter(
+      ([lat, lng, metric]) => lat != null && lng != null && metric != null,
+    );
+
+    const warnings = [];
+    const filteredRows = allPoints.length - points.length;
+    if (filteredRows > 0) {
+      warnings.push(
+        t`We filtered out ${filteredRows} row(s) containing null values.`,
+      );
+    }
+    // $FlowFixMe flow thinks warnings can be undefined
+    onUpdateWarnings(warnings);
+
     const bounds = L.latLngBounds(points);
 
     const min = d3.min(points, point => point[2]);
diff --git a/frontend/test/metabase/visualizations/components/PinMap.unit.spec.js b/frontend/test/metabase/visualizations/components/PinMap.unit.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..3fa8c95702e22e42b73448f7660e369772f0cae3
--- /dev/null
+++ b/frontend/test/metabase/visualizations/components/PinMap.unit.spec.js
@@ -0,0 +1,26 @@
+import PinMap from "metabase/visualizations/components/PinMap";
+
+describe("PinMap", () => {
+  it("should filter out rows with null values", () => {
+    const onUpdateWarnings = jest.fn();
+    const data = {
+      cols: ["lat", "lng", "metric"].map(name => ({ name })),
+      rows: [[null, 0, 0], [0, null, 0], [0, 0, null], [0, 0, 0]],
+    };
+    const props = {
+      settings: {
+        "map.latitude_column": "lat",
+        "map.longitude_column": "lng",
+        "map.metric_column": "metric",
+      },
+      series: [{ data }],
+      onUpdateWarnings,
+    };
+    const { points } = new PinMap(props)._getPoints(props);
+
+    expect(points).toEqual([[0, 0, 0]]);
+    expect(onUpdateWarnings.mock.calls[0][0]).toEqual([
+      "We filtered out 3 row(s) containing null values.",
+    ]);
+  });
+});