Wekan
Open source kanban board application built with Meteor
Alternative to: trello
v9.99
2026-07-17v9.99 2026-07-17 WeKan ® release
This release fixes the following BUG:
- LDAP connection leak: WeKan exhausted the directory server with “too many open connections”
(#6467, #6469).
Operators reported that after an update WeKan “dies really quickly”, that restarting the server did not
help, and that it “kills our openldap server with too many open connections”; others saw logins hang for
minutes and then fail with “Must be logged in”. Root cause: every LDAP login attempt
(
packages/wekan-ldap/server/loginHandler.js) and every background sync run (packages/wekan-ldap/server/sync.js) created a freshnew LDAP()and calledconnect(), but the code never calleddisconnect()on any path — success, failure, or fallback. Each login attempt (including every failed one) and each background-sync tick (every minute by default) therefore leaked one socket to the LDAP/AD server. Over time this grew without bound until the directory server hit its per-client connection limit and started refusing connections, which took it — and, with it, every WeKan login — down.- Fixed by guaranteeing the connection is always released:
- A small shared helper
packages/wekan-ldap/server/connectionGuard.js(runWithLdapDisconnect(ldap, fn)) runs the work anddisconnect()s in afinally, on every exit path. The disconnect is best-effort and never masks the original result or error. - The LDAP login handler now runs its whole flow through
runWithLdapDisconnect, soconnect()is always paired with adisconnect()— on a successful login, a thrownMeteor.Error, or a fallback to the default account system. - The background
sync()releases its connection in afinally, andimportNewUsers()disconnects only the connection it opened itself (never a connection borrowed fromsync()). - The admin
ldap_test_connectionmethod (packages/wekan-ldap/server/testConnection.js), which had the same leak, now disconnects on both the success and failure paths, so repeated “Test Connection” clicks no longer leak either. LDAP.disconnect()is now a safe no-op whenconnect()was never reached, so cleanup can never throw.
- A small shared helper
- Tests (
tests/ldapConnectionRelease.test.cjs, added totest:unit:node): behavioural coverage of the guard (disconnects after success and returns the result; disconnects exactly once; disconnects and re-throws when the work throws — the failed-login path that exhausted OpenLDAP), negative cases (a failing disconnect never turns a success into a failure nor hides the real error; a missing/nullldap is tolerated), plus source-level guards that the leak-prone call sites actually route through the guard and thatconnect()lives inside the guarded region. - Thanks to the reporting operators and xet7 (fix).
- Fixed by guaranteeing the connection is always released:
This release also updates the bundled FerretDB (see the fork’s own CHANGELOG Upcoming): the SQLite backend
connection pool no longer caps MaxOpenConns at 16, which had starved WeKan’s cursor-heavy load and made
boards take minutes to load and logins fail with “Must be logged in” (#6467,
#6469).
- Snap: FerretDB never becoming ready made WeKan hang with no web port and no explanation
(#6476). With
database=ferretdb,snap-src/bin/wekan-controlwaits for FerretDB to accept connections before starting WeKan — WeKan does not open its HTTP port until the database answers. That wait loop had no timeout and no diagnostics: if FerretDB never started listening (a crashed or CPU/architecture-incompatible per-arch binary, a locked or corrupt SQLite database, or the FerretDB service left disabled by a failed migration hand-off), WeKan blocked there forever. The service showed asactive, but the port never opened and the only symptom was a silentFerretDB not ready yet, retrying in 5 secondsrepeating — exactly what #6476 reported (Apache proxy could not connect to port 3333). The reporter’swekan.logstopped right after the startup env dump, confirming control never reachednode main.js.- Fixed by mirroring the MongoDB branch: after
WEKAN_DB_WAIT_TIMEOUTseconds (default 120, overridable) the FerretDB wait loop now prints an actionable hint once and keeps retrying — pointing tosnap logs <snap>.ferretdbfor the real error, naming the SQLite directory to check for locks/corruption, the arch-mismatch (exec format error) case, thesnap start --enable <snap>.ferretdbrecovery, and thesnap set <snap> database=mongodbfallback to keep working meanwhile. This turns “port never opens, no clue why” into a clear message. Regression test:tests/ferretdbWaitTimeout.test.cjs, including a negative guard that the FerretDB wait is not a silent unbounded loop again. - This is a robustness/diagnostics fix; the underlying reason FerretDB was not accepting connections is environment-specific and lives in the FerretDB service log.
- Thanks to uusijani (report) and xet7 (fix).
- Fixed by mirroring the MongoDB branch: after
Thanks to above for their contributions.