twentyhq/twenty · error · Error
Failed to persist relation join column index metadata for wo
Error message
Failed to persist relation join column index metadata for workspace ${workspaceId} What it means
Thrown by the 2.8 command that backfills relation join-column index metadata. It computes flatIndexBuildPlans and submits them via validateBuildAndRunLegacyWorkspaceMigration; on status === 'fail' it logs the report and throws. The report identifies which relation/index flat entity failed validation.
Source
Thrown at packages/twenty-server/src/database/commands/upgrade-version-command/2-8/2-8-workspace-command-1798100000000-backfill-relation-join-column-indexes.command.ts:220
flatEntityToCreate: flatIndexBuildPlans.map(
({ universalFlatIndexMetadata }) => universalFlatIndexMetadata,
),
flatEntityToDelete: [],
flatEntityToUpdate: [],
},
},
workspaceId,
applicationUniversalIdentifier:
twentyStandardFlatApplication.universalIdentifier,
},
);
if (validateAndBuildResult.status === 'fail') {
this.logger.error(
`Failed to persist relation join column index metadata:\n${JSON.stringify(validateAndBuildResult, null, 2)}`,
);
throw new Error(
`Failed to persist relation join column index metadata for workspace ${workspaceId}`,
);
}
this.logger.log(
`Successfully backfilled ${flatIndexBuildPlans.length} relation join column index(es) for workspace ${workspaceId}`,
);
}
}
View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Read the logged JSON report to find the failing relation/index and error code.
- Reconcile the relation metadata with the actual workspace schema (column exists, types match).
- Remove any duplicate/partial index metadata rows for that workspace, then re-run the 2.8 command.
Defensive patterns
Strategy: validation
Validate before calling
// Confirm the relation's join column exists in the workspace schema before building index plans:
for (const plan of flatIndexBuildPlans) {
const cols = await dataSource.query(`SELECT column_name FROM information_schema.columns WHERE table_schema=$1 AND table_name=$2`, [schema, plan.tableName]);
if (!cols.some(c => c.column_name === plan.columnName)) { /* reconcile relation metadata first */ }
} Try / catch
try {
await command.runOnWorkspace({ workspaceId, options });
} catch (e) {
logger.error({ workspaceId, err: e.message }, 'relation join column index backfill failed');
} Prevention
- Keep relation metadata consistent with the actual workspace schema (column names/types).
- Remove duplicate/partial index metadata rows before retrying.
- Avoid out-of-band DB edits to relation join columns.
When it happens
Trigger: A relation whose join column the index targets no longer exists or was renamed; the index metadata references a column absent from the workspace schema; a duplicate index definition collides with an existing one; the relation metadata is inconsistent with the actual DB schema (column/type mismatch).
Common situations: Workspaces with manually altered relations; cross-version upgrade where a relation was renamed in an intermediate release; schema drift between core metadata and the workspace schema after out-of-band DB edits; prior partial run that created some index metadata.
Related errors
- Failed to backfill imageIdentifierFieldMetadataId for worksp
- Failed to add NOT_RECORDED to CallRecording status metadata
- Failed to backfill standard skills for workspace ${workspace
- Failed to create the workspaceMember openRecordIn field for
- Failed to seed object openRecordIn for workspace ${workspace
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/66aa7630436a809a.
Report an issue: GitHub.