beekeeper-studio/beekeeper-studio · error
SurrealDB does not use traditional foreign key constraints.
Error message
SurrealDB does not use traditional foreign key constraints. Modify field definitions instead.
What it means
SurrealDB has no traditional FOREIGN KEY constraints to drop; relationships are expressed as record<...> typed fields. SurrealDBChangeBuilder.dropRelations() always throws, directing callers to change the field definitions instead.
Source
Thrown at apps/studio/src/shared/lib/sql/change_builder/SurrealDBChangeBuilder.ts:127
if (!drops?.length) return null;
return drops.map(spec =>
`REMOVE INDEX ${this.wrapIdentifier(spec.name)} ON TABLE ${this.wrapIdentifier(this.table)}`
).join('; ');
}
// SurrealDB uses record links instead of foreign keys
singleRelation(spec: CreateRelationSpec): string {
const fromColumn = this.wrapIdentifier(spec.fromColumn);
const toTable = this.wrapIdentifier(spec.toTable);
// In SurrealDB, we define a field that references another table
return `DEFINE FIELD ${fromColumn} ON TABLE ${this.wrapIdentifier(this.table)} TYPE record<${toTable}>`;
}
// SurrealDB doesn't have traditional foreign key constraints to drop
dropRelations(_names: string[]): string | null {
throw new Error('SurrealDB does not use traditional foreign key constraints. Modify field definitions instead.');
}
// Override the main alterTable method to handle SurrealDB's limitations
alterTable(spec: AlterTableSpec): string {
const statements: string[] = [];
// Handle column additions
if (spec.adds?.length) {
statements.push(...this.addColumns(spec.adds));
}
// Handle column drops
if (spec.drops?.length) {
statements.push(...this.dropColumns(spec.drops));
}
// Handle column alterations (type changes, defaults)
if (spec.alterations?.length) {View on GitHub (pinned to 4e3e03e322)
Solutions
- Redefine the referencing field's type (e.g. 'DEFINE FIELD other_id ON TABLE t TYPE string' or REMOVE FIELD) instead of dropping a constraint.
- Guard with a dialect check and skip dropRelations for SurrealDB connections.
- If the goal is removing a relationship entirely, run 'REMOVE FIELD <field> ON TABLE <table>'.
Example fix
// before builder.dropRelations(['fk_post_user']) // after "REMOVE FIELD user ON TABLE post;" // or redefine field TYPE
Defensive patterns
Strategy: fallback
Validate before calling
if (dialect === 'surrealdb') {
// no FK constraints: redefine or remove the referencing field instead
return names.map(f => `REMOVE FIELD ${f} ON TABLE ${table}`).join('; ')
}
builder.dropRelations(names) Type guard
const supportsForeignKeyDdl = (dialect: string) => dialect !== 'surrealdb'
Try / catch
try {
stmt = builder.dropRelations(names)
} catch (e) {
if (e.message.includes('foreign key constraints')) {
stmt = redefineOrRemoveReferenceFields(names) // REMOVE FIELD or change TYPE record<T>
} else throw e
} Prevention
- Hide FK constraint management for SurrealDB tables.
- Model relationships as record<T> typed fields and edit those instead.
- Branch migrations on dialect before touching constraints.
- Document SurrealDB's constraint model for plugin/script authors.
When it happens
Trigger: Any call to dropRelations(names) — e.g. an alter-table flow that removes FK constraints from a SurrealDB table, or a generic 'drop constraint' action in the schema editor.
Common situations: Running shared constraint-removal code paths written for SQL databases against SurrealDB; porting migration scripts with 'DROP CONSTRAINT' statements; cleaning up FKs before a table drop.
Related errors
- SurrealDB does not support nullable/not null constraints. Us
- SurrealDB does not support renaming fields directly. Create
- SurrealDB does not support column comments.
- Column reordering is not supported in SurrealDB.
- Mongo does not support truncation
AI-assisted analysis of beekeeper-studio/beekeeper-studio@4e3e03e322 (2026-08-31).
Data as JSON: /api/errors/06119dd33dece368.
Report an issue: GitHub.