n8n-io/n8n · error · NoNeedToReleaseEntityManagerError
Entity manager is not using single database connection and c
Error message
Entity manager is not using single database connection and cannot be released. Only entity managers created by connection#createEntityManagerWithSingleDatabaseConnection methods have a single database connection and they should be released.
What it means
EntityManager.release() is only meaningful for managers created via connection#createEntityManagerWithSingleDatabaseConnection (they own a single query runner). Calling release() on a default manager (which has no queryRunner) throws NoNeedToReleaseEntityManagerError. The guard prevents double-release and accidental release of pooled/shared managers.
Source
Thrown at packages/@n8n/typeorm/src/entity-manager/EntityManager.ts:1327
if (entityRepositoryInstance instanceof AbstractRepository) {
if (!(entityRepositoryInstance as any)['manager'])
(entityRepositoryInstance as any)['manager'] = this;
} else {
if (!entityMetadata) throw new CustomRepositoryCannotInheritRepositoryError(customRepository);
(entityRepositoryInstance as any)['manager'] = this;
(entityRepositoryInstance as any)['metadata'] = entityMetadata;
}
return entityRepositoryInstance;
}
/**
* Releases all resources used by entity manager.
* This is used when entity manager is created with a single query runner,
* and this single query runner needs to be released after job with entity manager is done.
*/
async release(): Promise<void> {
if (!this.queryRunner) throw new NoNeedToReleaseEntityManagerError();
return this.queryRunner.release();
}
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Only call release() on managers you created explicitly via `connection.createQueryRunner().manager` (and pair with queryRunner.release()) or via `createEntityManagerWithSingleDatabaseConnection`.
- For the default manager (`connection.manager`), do not call release() — the DataSource owns it.
- Remove unconditional release() from finally blocks; gate it behind a flag indicating you created the manager.
Example fix
// before - releasing the shared default manager
const manager = dataSource.manager;
try { await manager.save(User, u); }
finally { await manager.release(); } // -> throws
// after - default manager is owned by the DataSource
const manager = dataSource.manager;
await manager.save(User, u);
// no release() — DataSource manages it Defensive patterns
Strategy: validation
Validate before calling
function isOwnsQueryRunner(manager: EntityManager): boolean {
return !!manager.queryRunner;
}
// only release managers you created explicitly
if (isOwnsQueryRunner(manager)) {
await manager.release();
} Prevention
- Never call release() on connection.manager / dataSource.manager.
- Only release managers from createQueryRunner().manager or createEntityManagerWithSingleDatabaseConnection.
- Track ownership with a flag if a helper wraps arbitrary managers.
- Remove unconditional release() from finally blocks.
When it happens
Trigger: Calling `manager.release()` on the default EntityManager obtained from `connection.manager` or `dataSource.manager`; calling release() twice; releasing a manager that was never tied to a single query runner.
Common situations: Generic cleanup code that always calls release() in finally; copy-paste from a single-connection example into multi-connection code; helper that wraps any manager and tries to release it.
Related errors
- Driver not Connected
- Transaction method requires callback in second parameter if
- Database connection provided by a query runner was already r
- Column "${columnName}" was not found in table "${metadata.na
- You must provide selection conditions in order to find a sin
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/8d55b93e4554cb11.
Report an issue: GitHub.