Budibase/budibase · error · Error

Column names can't contain special characters

Error message

Column names can't contain special characters

What it means

`validateTable` in LinkController runs when a table is saved. For link-type schema entries with a fieldName (and not autocolumns), it enforces the ValidColumnNameRegex; names containing special characters (spaces, symbols, etc.) would break link document storage and lookups, so saving throws 'Column names can't contain special characters'.

Source

Thrown at packages/server/src/db/linkedRows/LinkController.ts:106

      includeDocs: IncludeDocs.INCLUDE,
    })) as LinkDocument[]
  }

  /**
   * Makes sure the passed in table schema contains valid relationship structures.
   */
  validateTable(table: Table) {
    const usedAlready = []
    for (let schema of Object.values(table.schema)) {
      if (schema.type !== FieldType.LINK) {
        continue
      }
      if (
        schema.fieldName &&
        !schema.autocolumn &&
        !schema.fieldName.match(ValidColumnNameRegex)
      ) {
        throw new Error("Column names can't contain special characters")
      }
      const unique = schema.tableId! + schema?.fieldName
      if (usedAlready.indexOf(unique) !== -1) {
        throw new Error(
          "Cannot re-use the linked column name for a linked table."
        )
      }
      usedAlready.push(unique)
    }
  }

  /**
   * Returns whether the two link schemas are equal (in the important parts, not a pure equality check)
   */
  areLinkSchemasEqual(linkSchema1: FieldSchema, linkSchema2: FieldSchema) {
    const compareFields = [
      "name",
      "type",

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Rename the link column to only letters, digits and underscores (matching ValidColumnNameRegex), e.g. "user_links".
  2. If importing data, sanitize headers to a safe charset before creating tables.
  3. Use the column's display name feature for human-readable labels instead of encoding them in fieldName.

Example fix

// before
{ "name": "Order Items!", "type": "link" }
// after
{ "name": "order_items", "type": "link", "displayName": "Order Items" }
Defensive patterns

Strategy: validation

Validate before calling

const ValidColumnNameRegex = /^[a-zA-Z0-9_]+$/
for (const [name, schema] of Object.entries(table.schema)) {
  if (schema.type === "link" && !ValidColumnNameRegex.test(name)) {
    throw new Error(`Link column '${name}' must only contain letters, digits and underscores`)
  }
}

Try / catch

try {
  await api.post(`/tables`, table)
} catch (err) {
  if (err.message.includes("special characters")) {
    table.schema = sanitizeColumnNames(table.schema)
    return api.post(`/tables`, table)
  }
  throw err
}

Prevention

When it happens

Trigger: Saving a table whose link column name contains characters outside the allowed regex, e.g. "My Links!", "user-roles #1", or a name with spaces or emoji; renaming a link column via the API to a value with slashes or dots.

Common situations: Users create columns with friendly display names containing spaces or punctuation; an app imported from a CSV/Excel where headers became column names with special characters; API scripts generating column names from arbitrary labels.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/d6deb1e313ae9d2c. Report an issue: GitHub.