diff --git a/packages/server/src/api/controllers/table/index.js b/packages/server/src/api/controllers/table/index.js
index b8e3e56e3a..93f4ec9f94 100644
--- a/packages/server/src/api/controllers/table/index.js
+++ b/packages/server/src/api/controllers/table/index.js
@@ -89,16 +89,20 @@ exports.save = async function(ctx) {
   }
 
   // update linked rows
-  const linkResp = await linkRows.updateLinks({
-    appId,
-    eventType: oldTable
-      ? linkRows.EventType.TABLE_UPDATED
-      : linkRows.EventType.TABLE_SAVE,
-    table: tableToSave,
-    oldTable: oldTable,
-  })
-  if (linkResp != null && linkResp._rev) {
-    tableToSave._rev = linkResp._rev
+  try {
+    const linkResp = await linkRows.updateLinks({
+      appId,
+      eventType: oldTable
+        ? linkRows.EventType.TABLE_UPDATED
+        : linkRows.EventType.TABLE_SAVE,
+      table: tableToSave,
+      oldTable: oldTable,
+    })
+    if (linkResp != null && linkResp._rev) {
+      tableToSave._rev = linkResp._rev
+    }
+  } catch (err) {
+    ctx.throw(400, err)
   }
 
   // don't perform any updates until relationships have been
diff --git a/packages/server/src/db/linkedRows/LinkController.js b/packages/server/src/db/linkedRows/LinkController.js
index d202c07d63..199b8f5755 100644
--- a/packages/server/src/db/linkedRows/LinkController.js
+++ b/packages/server/src/db/linkedRows/LinkController.js
@@ -3,6 +3,7 @@ const { IncludeDocs, getLinkDocuments } = require("./linkUtils")
 const { generateLinkID } = require("../utils")
 const Sentry = require("@sentry/node")
 const { FieldTypes } = require("../../constants")
+const { isEqual } = require("lodash")
 
 /**
  * Creates a new link document structure which can be put to the database. It is important to
@@ -113,6 +114,23 @@ class LinkController {
     })
   }
 
+  /**
+   * Makes sure the passed in table schema contains valid relationship structures.
+   */
+  validateTable(table) {
+    const usedAlready = []
+    for (let schema of Object.values(table.schema)) {
+      if (schema.type !== FieldTypes.LINK) {
+        continue
+      }
+      const unique = schema.tableId + schema.fieldName
+      if (usedAlready.indexOf(unique) !== -1) {
+        throw "Cannot re-use the linked column name for a linked table."
+      }
+      usedAlready.push(unique)
+    }
+  }
+
   // all operations here will assume that the table
   // this operation is related to has linked rows
   /**
@@ -246,6 +264,8 @@ class LinkController {
    */
   async tableSaved() {
     const table = await this.table()
+    // validate the table first
+    this.validateTable(table)
     const schema = table.schema
     for (let fieldName of Object.keys(schema)) {
       const field = schema[fieldName]
@@ -269,6 +289,11 @@ class LinkController {
         if (field.autocolumn) {
           linkConfig.autocolumn = field.autocolumn
         }
+        // check the linked table to make sure we aren't overwriting an existing column
+        const existingSchema = linkedTable.schema[field.fieldName]
+        if (existingSchema != null && !isEqual(existingSchema, linkConfig)) {
+          throw "Cannot overwrite existing column."
+        }
         // create the link field in the other table
         linkedTable.schema[field.fieldName] = linkConfig
         const response = await this._db.put(linkedTable)