remix-run/remix · error · DataTableValidationError

Unknown column "' + key + '" for table "' + tableName + '"

Error message

Unknown column "' + key + '" for table "' + tableName + '"

What it means

After confirming the written value is an object, the library checks each key against the table's declared columns via getTableColumns. A key that is not a column of that table produces a DataTableValidationError naming the unknown column — this catches typos and renamed columns before they reach SQL, and also prevents accidental injection of stray properties.

Source

Thrown at packages/data-table/src/lib/database/write-lifecycle.ts:382

      {
        metadata: {
          table: tableName,
          operation,
          ...(source ? { source } : {}),
        },
      },
    )
  }

  let output: Record<string, unknown> = {}

  for (let key in value) {
    if (!Object.prototype.hasOwnProperty.call(value, key)) {
      continue
    }

    if (!Object.prototype.hasOwnProperty.call(columns, key)) {
      throw new DataTableValidationError(
        'Unknown column "' + key + '" for table "' + tableName + '"',
        [],
        {
          metadata: {
            table: tableName,
            column: key,
            operation,
            ...(source ? { source } : {}),
          },
        },
      )
    }

    output[key] = (value as Record<string, unknown>)[key]
  }

  return output
}

View on GitHub (pinned to 9696913134)

Solutions

  1. Fix the property name to match a declared column exactly
  2. Whitelist/pick only known columns before writing: pick(values, ...columnNames)
  3. If the field should exist, add the column to defineTable first

Example fix

// before
await userTable.create({ values: req.json() }) // contains extra fields

// after
let body = req.json()
await userTable.create({
  values: { name: body.name, email: body.email },
})
Defensive patterns

Strategy: validation

Validate before calling

let allowed = new Set(Object.keys(getTableColumns(table)))
let safe = Object.fromEntries(Object.entries(values).filter(([k]) => allowed.has(k)))
await table.create({ values: safe })

Type guard

function hasOnlyKnownColumns(values: Record<string, unknown>, columns: Record<string, unknown>): boolean {
  return Object.keys(values).every((key) => Object.prototype.hasOwnProperty.call(columns, key))
}

Try / catch

try {
  await table.create({ values })
} catch (error) {
  if (error instanceof DataTableValidationError && /Unknown column/.test(error.message)) {
    return new Response(error.message, { status: 400 })
  } else throw error
}

Prevention

When it happens

Trigger: create({ values: { emial: 'a@b.com' } }) with the column spelled email; sending request JSON that includes extra fields (timestamps, ids, nested objects) not declared on the table; referencing a column after renaming it in the schema.

Common situations: Unvalidated request bodies forwarded straight into write APIs; schema drift between an API client and the table definition; spreading objects that carry extra metadata (e.g. joined rows) into an update.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/3bce50e698329ada. Report an issue: GitHub.