remix-run/remix · error · Error

onDelete() requires references() to be set first

Error message

onDelete() requires references() to be set first

What it means

ColumnBuilder.onDelete(action) sets the referential action for a foreign key, but it mutates the references() configuration that must already exist on the column. If references() was not called first, there is nothing to attach onDelete to, so the builder throws.

Source

Thrown at packages/data-table/src/lib/column.ts:140

    this.#definition.references = {
      table: toTableRef(table),
      columns: Array.isArray(columns) ? [...columns] : [columns],
      onDelete: this.#definition.references?.onDelete,
      onUpdate: this.#definition.references?.onUpdate,
      name,
    }
    return this
  }

  /**
   * Sets the foreign-key action used when the referenced row is deleted.
   * @param action Delete action to apply.
   * @returns The column builder.
   */
  onDelete(action: ForeignKeyAction): ColumnBuilder<output> {
    if (!this.#definition.references) {
      throw new Error('onDelete() requires references() to be set first')
    }

    this.#definition.references.onDelete = action
    return this
  }

  /**
   * Sets the foreign-key action used when the referenced row is updated.
   * @param action Update action to apply.
   * @returns The column builder.
   */
  onUpdate(action: ForeignKeyAction): ColumnBuilder<output> {
    if (!this.#definition.references) {
      throw new Error('onUpdate() requires references() to be set first')
    }

    this.#definition.references.onUpdate = action
    return this

View on GitHub (pinned to 9696913134)

Solutions

  1. Call references() before onDelete(): column.integer('user_id').references(() => users.id).onDelete('cascade').
  2. If the column is intentionally not a foreign key, remove the onDelete() call.

Example fix

// before
userId: t.integer('user_id').onDelete('cascade')

// after
userId: t.integer('user_id').references(() => t2.id).onDelete('cascade')
Defensive patterns

Strategy: validation

Validate before calling

// Always build foreign keys as one chained expression so references() precedes onDelete()
userId: (t) => t.integer('user_id').references(() => users.id).onDelete('cascade')

Prevention

When it happens

Trigger: Chaining .onDelete('cascade') on a column builder before calling .references(() => otherTable.id), or splitting the calls and forgetting references().

Common situations: Refactoring schema files and dropping the references() line; ordering chained builder calls incorrectly; copy-pasting a column definition that references a table not yet defined so references() was removed.

Related errors


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