From b8cda55e5713eec92328abc22dc794afe3c17bfc Mon Sep 17 00:00:00 2001 From: "n8n-cat-bot[bot]" <283985454+n8n-cat-bot[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 11:43:27 +0000 Subject: [PATCH] fix(editor): Sorting data table rows by unknown column returns raw database error (#39733) Co-authored-by: n8n-cat-bot[bot] --- .../data-table.service.integration.test.ts | 34 +++++++++++++++++++ .../modules/data-table/data-table.service.ts | 9 +++++ .../public-api/data-tables.test.ts | 16 +++++++++ 3 files changed, 59 insertions(+) diff --git a/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts b/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts index c6844ab5721..10e75c730bf 100644 --- a/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts +++ b/packages/cli/src/modules/data-table/__tests__/data-table.service.integration.test.ts @@ -3475,6 +3475,40 @@ describe('dataTable', () => { }); describe('getManyRowsAndCount', () => { + it('rejects a sort column that does not exist', async () => { + const { id: dataTableId } = await dataTableService.createDataTable(project1.id, { + name: 'dataTable', + columns: [{ name: 'name', type: 'string' }], + }); + await dataTableService.insertRows(dataTableId, project1.id, [{ name: 'Alice' }]); + + const result = dataTableService.getManyRowsAndCount(dataTableId, project1.id, { + sortBy: ['bogusCol', 'ASC'], + }); + + await expect(result).rejects.toThrow(DataTableValidationError); + await expect(result).rejects.toThrow( + "Validation error with data table request: unknown column name 'bogusCol'", + ); + }); + + it.each(['name', 'id', 'createdAt', 'updatedAt'])( + 'sorts by existing column %s', + async (columnName) => { + const { id: dataTableId } = await dataTableService.createDataTable(project1.id, { + name: 'dataTable', + columns: [{ name: 'name', type: 'string' }], + }); + await dataTableService.insertRows(dataTableId, project1.id, [{ name: 'Alice' }]); + + const result = await dataTableService.getManyRowsAndCount(dataTableId, project1.id, { + sortBy: [columnName, 'ASC'], + }); + expect(result.count).toBe(1); + expect(result.data[0].name).toBe('Alice'); + }, + ); + it('retrieves rows correctly', async () => { // ARRANGE const { id: dataTableId } = await dataTableService.createDataTable(project1.id, { diff --git a/packages/cli/src/modules/data-table/data-table.service.ts b/packages/cli/src/modules/data-table/data-table.service.ts index 23f4d12a0b1..613ecb52c72 100644 --- a/packages/cli/src/modules/data-table/data-table.service.ts +++ b/packages/cli/src/modules/data-table/data-table.service.ts @@ -335,6 +335,15 @@ export class DataTableService { return await this.dataTableColumnRepository.manager.transaction(async (em) => { const columns = await this.dataTableColumnRepository.getColumns(dataTableId, em); + const sortColumn = dto.sortBy?.[0]; + if ( + sortColumn && + !Object.hasOwn(DATA_TABLE_SYSTEM_COLUMN_TYPE_MAP, sortColumn) && + !columns.some((column) => column.name === sortColumn) + ) { + throw new DataTableValidationError(`unknown column name '${sortColumn}'`); + } + const transformedDto = dto.filter ? { ...dto, filter: this.validateAndTransformFilters(dto.filter, columns) } : dto; diff --git a/packages/cli/test/integration/public-api/data-tables.test.ts b/packages/cli/test/integration/public-api/data-tables.test.ts index 02b3c427279..8b74f12d49a 100644 --- a/packages/cli/test/integration/public-api/data-tables.test.ts +++ b/packages/cli/test/integration/public-api/data-tables.test.ts @@ -963,6 +963,22 @@ describe('GET /data-tables/:dataTableId/rows', () => { expect(response.body.message).toBe('Invalid sort direction'); }); + test('should reject an unknown sort column', async () => { + const dataTable = await createDataTable(ownerPersonalProject, { + columns: [{ name: 'name', type: 'string' }], + data: [{ name: 'Alice' }], + }); + + const response = await authOwnerAgent + .get(`/data-tables/${dataTable.id}/rows`) + .query({ sortBy: 'bogusCol:asc' }); + + expect(response.statusCode).toBe(400); + expect(response.body.message).toBe( + "Validation error with data table request: unknown column name 'bogusCol'", + ); + }); + test('should sort by system column (id)', async () => { const dataTable = await createDataTable(ownerPersonalProject, { columns: [{ name: 'name', type: 'string' }],