Hitting a unique constraint in a sql transaction results in app crash

* Describe the bug

when I hit a unqiue constraint validation error that’s wrapped inside a sql transaction, the workflow won’t result in an error, but instead crash the app and it stays in ‘ongoing state’ until manual abortion.

* Environment

  • NocoBase version: v2.0.29
  • Database type and version: PostgreSQL 17
  • OS: Linux
  • Deployment Methods: Docker
  • Docker image version: nocobase/nocobase:latest

* How To Reproduce

create a workflow of any type and add a sql action with this content (assuming that there’s an exisiting user with admin@nocobase.com as the email)

BEGIN;
INSERT INTO users (email) VALUES ('admin@nocobase.com');
COMMIT;

Expected behavior

the workflow should’ve resulted in an error instead of ongoing indefinitely

Screenshots

Logs

{“level”:“error”,“error”:{“name”:“SequelizeUniqueConstraintError”,“errors”:[{“message”:“email must be unique”,“type”:“unique violation",“path”:“email”,“value”:"admin@nocobase.com”,“origin”:“DB”,“instance”:null,“validatorKey”:“not_unique”,“validatorName”:null,“validatorArgs”:}],“parent”:{“length”:212,“name”:“error”,“severity”:“ERROR”,“code”:“23505”,“detail”:“Key (email)=(admin@nocobase.com) already exists.”,“schema”:“public”,“table”:“users”,“constraint”:“users_email_key”,“file”:“nbtinsert.c”,“line”:“673”,“routine”:“_bt_check_unique”,“sql”:“BEGIN;\nUPDATE users SET email = ‘admin@nocobase.com’ WHERE id = 1;\nINSERT INTO users (email) VALUES (‘admin@nocobase.com’);\nCOMMIT;”},“original”:{“length”:212,“name”:“error”,“severity”:“ERROR”,“code”:“23505”,“detail”:“Key (email)=(admin@nocobase.com) already exists.”,“schema”:“public”,“table”:“users”,“constraint”:“users_email_key”,“file”:“nbtinsert.c”,“line”:“673”,“routine”:“_bt_check_unique”,“sql”:“BEGIN;\nUPDATE users SET email = ‘admin@nocobase.com’ WHERE id = 1;\nINSERT INTO users (email) VALUES (‘admin@nocobase.com’);\nCOMMIT;”},“fields”:{“email":"admin@nocobase.com”},“sql”:“BEGIN;\nUPDATE users SET email = ‘admin@nocobase.com’ WHERE id = 1;\nINSERT INTO users (email) VALUES (‘admin@nocobase.com’);\nCOMMIT;”},“workflowId”:362696944320513,“message”:"execution (362697040789504) run instruction [sql] for node (362696944320514) failed: ",“timestamp”:“2026-05-05 15:57:06”}

{“level”:“info”,“workflowId”:362696944320513,“message”:“execution (362697040789504) run instruction [sql] for node (362696944320514) finished as status: -2”,“timestamp”:“2026-05-05 15:57:06”}

{“level”:“error”,“name”:“SequelizeDatabaseError”,“parent”:{“length”:144,“name”:“error”,“severity”:“ERROR”,“code”:“25P02”,“file”:“postgres.c”,“line”:“1144”,“routine”:“exec_simple_query”,“sql”:“INSERT INTO "jobs" ("createdAt","updatedAt","id","executionId","nodeId","nodeKey","status","result") VALUES (‘2026-05-05 15:57:06.244 +07:00’,‘2026-05-05 15:57:06.244 +07:00’,‘12350370185501696’,362697040789504,362696944320514,‘6skr5483ivo’,-2,‘{"message":"Validation error","name":"SequelizeUniqueConstraintError","errors":[{"message":"email must be unique","type":"unique violation","path":"email","value":"admin@nocobase.com","origin":"DB","instance":null,"validatorKey":"not_unique","validatorName":null,"validatorArgs":}],"parent":{"length":212,"name":"error","severity":"ERROR","code":"23505","detail":"Key (email)=(admin@nocobase.com) already exists.","schema":"public","table":"users","constraint":"users_email_key","file":"nbtinsert.c","line":"673","routine":"_bt_check_unique","sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"},"original":{"length":212,"name":"error","severity":"ERROR","code":"23505","detail":"Key (email)=(admin@nocobase.com) already exists.","schema":"public","table":"users","constraint":"users_email_key","file":"nbtinsert.c","line":"673","routine":"_bt_check_unique","sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"},"fields":{"email":"admin@nocobase.com"},"sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"}’);”},“original”:{“length”:144,“name”:“error”,“severity”:“ERROR”,“code”:“25P02”,“file”:“postgres.c”,“line”:“1144”,“routine”:“exec_simple_query”,“sql”:“INSERT INTO "jobs" ("createdAt","updatedAt","id","executionId","nodeId","nodeKey","status","result") VALUES (‘2026-05-05 15:57:06.244 +07:00’,‘2026-05-05 15:57:06.244 +07:00’,‘12350370185501696’,362697040789504,362696944320514,‘6skr5483ivo’,-2,‘{"message":"Validation error","name":"SequelizeUniqueConstraintError","errors":[{"message":"email must be unique","type":"unique violation","path":"email","value":"admin@nocobase.com","origin":"DB","instance":null,"validatorKey":"not_unique","validatorName":null,"validatorArgs":}],"parent":{"length":212,"name":"error","severity":"ERROR","code":"23505","detail":"Key (email)=(admin@nocobase.com) already exists.","schema":"public","table":"users","constraint":"users_email_key","file":"nbtinsert.c","line":"673","routine":"_bt_check_unique","sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"},"original":{"length":212,"name":"error","severity":"ERROR","code":"23505","detail":"Key (email)=(admin@nocobase.com) already exists.","schema":"public","table":"users","constraint":"users_email_key","file":"nbtinsert.c","line":"673","routine":"_bt_check_unique","sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"},"fields":{"email":"admin@nocobase.com"},"sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"}’);”},“sql”:“INSERT INTO "jobs" ("createdAt","updatedAt","id","executionId","nodeId","nodeKey","status","result") VALUES (‘2026-05-05 15:57:06.244 +07:00’,‘2026-05-05 15:57:06.244 +07:00’,‘12350370185501696’,362697040789504,362696944320514,‘6skr5483ivo’,-2,‘{"message":"Validation error","name":"SequelizeUniqueConstraintError","errors":[{"message":"email must be unique","type":"unique violation","path":"email","value":"admin@nocobase.com","origin":"DB","instance":null,"validatorKey":"not_unique","validatorName":null,"validatorArgs":}],"parent":{"length":212,"name":"error","severity":"ERROR","code":"23505","detail":"Key (email)=(admin@nocobase.com) already exists.","schema":"public","table":"users","constraint":"users_email_key","file":"nbtinsert.c","line":"673","routine":"_bt_check_unique","sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"},"original":{"length":212,"name":"error","severity":"ERROR","code":"23505","detail":"Key (email)=(admin@nocobase.com) already exists.","schema":"public","table":"users","constraint":"users_email_key","file":"nbtinsert.c","line":"673","routine":"_bt_check_unique","sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"},"fields":{"email":"admin@nocobase.com"},"sql":"BEGIN;\nUPDATE users SET email = ‘‘admin@nocobase.com’’ WHERE id = 1;\nINSERT INTO users (email) VALUES (’‘admin@nocobase.com’‘);\nCOMMIT;"}’);”,“parameters”:{},“message”:“execution (362697040789504) error: current transaction is aborted, commands ignored until end of transaction block current transaction is aborted, commands ignored until end of transaction block”,“stack”:“Error\n at Query.run (/app/nocobase/node_modules/sequelize/lib/dialects/postgres/query.js:50:25)\n at /app/nocobase/node_modules/sequelize/lib/sequelize.js:315:28\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async PostgresQueryInterface.bulkInsert (/app/nocobase/node_modules/sequelize/lib/dialects/abstract/query-interface.js:346:21)\n at async recursiveBulkCreate (/app/nocobase/node_modules/sequelize/lib/model.js:1697:25)\n at async jobs.bulkCreate (/app/nocobase/node_modules/sequelize/lib/model.js:1786:12)\n at async Processor.exit (/app/nocobase/node_modules/@nocobase/plugin-workflow/dist/server/Processor.js:299:9)\n at async Processor.start (/app/nocobase/node_modules/@nocobase/plugin-workflow/dist/server/Processor.js:159:7)\n at async Dispatcher.process (/app/nocobase/node_modules/@nocobase/plugin-workflow/dist/server/Dispatcher.js:405:7)\n at async execute (/app/nocobase/node_modules/@nocobase/plugin-workflow/dist/server/actions/workflows.js:150:17)\n at async middleware (/app/nocobase/node_modules/@nocobase/plugin-workflow-request-interceptor/dist/server/RequestInterceptionTrigger.js:143:5)\n at async triggerWorkflowActionMiddleware (/app/nocobase/node_modules/@nocobase/plugin-workflow-action-trigger/dist/server/ActionTrigger.js:61:7)\n at async dataTemplate (/app/nocobase/node_modules/@nocobase/server/lib/middlewares/data-template.js:36:3)\n at async /app/nocobase/node_modules/@nocobase/plugin-users/dist/server/server.js:208:7\n at async deleteRolesCache (/app/nocobase/node_modules/@nocobase/plugin-users/dist/server/server.js:197:7)\n at async handleFieldSourceMiddleware (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:463:7)\n at async mergeReverseFieldWhenSaveCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:413:7)\n at async templateDataMiddleware (/app/nocobase/node_modules/@nocobase/plugin-block-template/dist/server/middlewares/templateData.js:45:3)\n at async pushUISchemaWhenUpdateCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:374:7)\n at async pushUISchemaWhenUpdateCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:355:7)\n at async appendDataToRolesCheck (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/plugin.js:567:7)\n at async loadDataSourceTablesIntoCollections (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/middlewares/load-tables.js:88:3)”,“timestamp”:“2026-05-05 15:57:06”}

{“level”:“error”,“message”:“current transaction is aborted, commands ignored until end of transaction block”,“extra”:{“method”:“error-handler”,“err”:“Error\n at Query.run (/app/nocobase/node_modules/sequelize/lib/dialects/postgres/query.js:50:25)\n at /app/nocobase/node_modules/sequelize/lib/sequelize.js:315:28\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async PostgresQueryInterface.startTransaction (/app/nocobase/node_modules/sequelize/lib/dialects/abstract/query-interface.js:526:12)\n at async Transaction.begin (/app/nocobase/node_modules/sequelize/lib/transaction.js:111:7)\n at async Transaction.prepareEnvironment (/app/nocobase/node_modules/sequelize/lib/transaction.js:89:7)\n at async /app/nocobase/node_modules/sequelize/lib/sequelize.js:504:7\n at async execute (/app/nocobase/node_modules/@nocobase/plugin-workflow/dist/server/actions/workflows.js:162:18)\n at async middleware (/app/nocobase/node_modules/@nocobase/plugin-workflow-request-interceptor/dist/server/RequestInterceptionTrigger.js:143:5)\n at async triggerWorkflowActionMiddleware (/app/nocobase/node_modules/@nocobase/plugin-workflow-action-trigger/dist/server/ActionTrigger.js:61:7)\n at async dataTemplate (/app/nocobase/node_modules/@nocobase/server/lib/middlewares/data-template.js:36:3)\n at async /app/nocobase/node_modules/@nocobase/plugin-users/dist/server/server.js:208:7\n at async deleteRolesCache (/app/nocobase/node_modules/@nocobase/plugin-users/dist/server/server.js:197:7)\n at async handleFieldSourceMiddleware (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:463:7)\n at async mergeReverseFieldWhenSaveCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:413:7)\n at async templateDataMiddleware (/app/nocobase/node_modules/@nocobase/plugin-block-template/dist/server/middlewares/templateData.js:45:3)\n at async pushUISchemaWhenUpdateCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:374:7)\n at async pushUISchemaWhenUpdateCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:355:7)\n at async appendDataToRolesCheck (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/plugin.js:567:7)\n at async loadDataSourceTablesIntoCollections (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/middlewares/load-tables.js:88:3)\n at async setDataSourceListDefaultSort (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/plugin.js:313:7)\n at async showAnonymous (/app/nocobase/node_modules/@nocobase/plugin-acl/dist/server/server.js:488:7)”},“meta”:{“err”:“Error\n at Query.run (/app/nocobase/node_modules/sequelize/lib/dialects/postgres/query.js:50:25)\n at /app/nocobase/node_modules/sequelize/lib/sequelize.js:315:28\n at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n at async PostgresQueryInterface.startTransaction (/app/nocobase/node_modules/sequelize/lib/dialects/abstract/query-interface.js:526:12)\n at async Transaction.begin (/app/nocobase/node_modules/sequelize/lib/transaction.js:111:7)\n at async Transaction.prepareEnvironment (/app/nocobase/node_modules/sequelize/lib/transaction.js:89:7)\n at async /app/nocobase/node_modules/sequelize/lib/sequelize.js:504:7\n at async execute (/app/nocobase/node_modules/@nocobase/plugin-workflow/dist/server/actions/workflows.js:162:18)\n at async middleware (/app/nocobase/node_modules/@nocobase/plugin-workflow-request-interceptor/dist/server/RequestInterceptionTrigger.js:143:5)\n at async triggerWorkflowActionMiddleware (/app/nocobase/node_modules/@nocobase/plugin-workflow-action-trigger/dist/server/ActionTrigger.js:61:7)\n at async dataTemplate (/app/nocobase/node_modules/@nocobase/server/lib/middlewares/data-template.js:36:3)\n at async /app/nocobase/node_modules/@nocobase/plugin-users/dist/server/server.js:208:7\n at async deleteRolesCache (/app/nocobase/node_modules/@nocobase/plugin-users/dist/server/server.js:197:7)\n at async handleFieldSourceMiddleware (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:463:7)\n at async mergeReverseFieldWhenSaveCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:413:7)\n at async templateDataMiddleware (/app/nocobase/node_modules/@nocobase/plugin-block-template/dist/server/middlewares/templateData.js:45:3)\n at async pushUISchemaWhenUpdateCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:374:7)\n at async pushUISchemaWhenUpdateCollectionField (/app/nocobase/node_modules/@nocobase/plugin-data-source-main/dist/server/server.js:355:7)\n at async appendDataToRolesCheck (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/plugin.js:567:7)\n at async loadDataSourceTablesIntoCollections (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/middlewares/load-tables.js:88:3)\n at async setDataSourceListDefaultSort (/app/nocobase/node_modules/@nocobase/plugin-data-source-manager/dist/server/plugin.js:313:7)\n at async showAnonymous (/app/nocobase/node_modules/@nocobase/plugin-acl/dist/server/server.js:488:7)”},“module”:“workflows”,“submodule”:“execute”,“method”:“error-handler”,“app”:“main”,“reqId”:“1e4e8351-16dd-482c-a421-6417acad94c3”,“dataSourceKey”:“main”,“timestamp”:“2026-05-05 15:57:06”}

{“level”:“error”,“message”:“response /api/workflows:execute?filterByTk=362696944320513&autoRevision=1”,“method”:“POST”,“path”:“/api/workflows:execute?filterByTk=362696944320513&autoRevision=1”,“res”:[{“message”:“current transaction is aborted, commands ignored until end of transaction block”}],“action”:{“actionName”:“execute”,“resourceName”:“workflows”,“params”:{“filterByTk”:“362696944320513”,“autoRevision”:“1”,“resourceName”:“workflows”,“actionName”:“execute”,“values”:{“data”:{“createdAt”:“2026-04-01T07:01:32.979Z”,“updatedAt”:“2026-04-01T07:01:32.979Z”,“id”:1,“nickname”:“Super Admin",“username”:“nocobase”,“email”:"admin@nocobase.com”,“phone”:null,“passwordChangeTz”:null,“appLang”:null,“systemSettings”:{},“createdById”:null,“updatedById”:1},“userId”:1,“roleName”:null},“filter”:{“key”:“itrtmd4xl84”}}},“userId”:1,“username”:“nocobase”,“status”:500,“cost”:189,“app”:“main”,“reqId”:“1e4e8351-16dd-482c-a421-6417acad94c3”,“bodySize”:106,“timestamp”:“2026-05-05 15:57:06”}

Hello, I tested this SQL statement, and the system did not crash. I suggest using: INSERT INTO users (email) VALUES ('admin@nocobase.com') directly; code blocks are not supported.

Thank you for your response. by code blocks, you mean the BEGIN and COMMIT block? of course they are the problem in the first place. without the transaction, it won’t crash the app. Thank you nonetheless.