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”}