wekan/wekan · error · Meteor.Error

${error.name || error.message}

Error message

${error.name || error.message}

What it means

After connecting successfully, the bind step (bindIfNecessary) runs inside runWithLdapDisconnect; if the bind rejects, the error is rethrown as new Meteor.Error(error.name || error.message). This surfaces directory-level bind errors — typically LDAPInvalidCredentials (error.name 49/invalidCredentials) or client-timeout names — to the admin as the Test Connection failure reason.

Source

Thrown at packages/wekan-ldap/server/testConnection.js:40

      ldap = new LDAP();
      await ldap.connect();
    } catch (error) {
      console.log(error);
      // #6467/#6469: release anything opened before rethrowing, so a failed
      // "Test Connection" does not leak a socket to the directory server.
      if (ldap) {
        await ldap.disconnect();
      }
      throw new Meteor.Error(error.message);
    }

    // #6467/#6469: always disconnect the test connection (success or failure),
    // otherwise repeated admin "Test Connection" clicks leak connections too.
    return await runWithLdapDisconnect(ldap, async () => {
      try {
        await ldap.bindIfNecessary();
      } catch (error) {
        throw new Meteor.Error(error.name || error.message);
      }

      return {
        message: 'Connection_success',
        params: [],
      };
    });
  },
});

View on GitHub (pinned to eb1433158b)

Solutions

  1. Verify the bind credentials out-of-band: ldapsearch -H <url> -D <LDAP_BIND_DN> -w <LDAP_BIND_PASS> -b '' -s base.
  2. Use the full distinguished name for the bind user (e.g. cn=svc-wekan,ou=svc,dc=example,dc=com).
  3. Check the bind account is not expired/locked and its password matches the WeKan LDAP_BIND_PASS setting exactly.
  4. If no bind user is intended, confirm the directory permits anonymous search binds.
  5. Fix the setting and re-run Test Connection; the disconnect guard ensures no socket leaks between attempts.

Example fix

// before
LDAP_BIND_DN = 'svc-wekan'                 // not a DN -> invalidCredentials
LDAP_BIND_PASS = 'old-password'
// after
LDAP_BIND_DN = 'cn=svc-wekan,ou=services,dc=example,dc=com'
LDAP_BIND_PASS = 'current-password'
Defensive patterns

Strategy: try-catch

Validate before calling

// verify bind credentials out-of-band before clicking Test Connection
// ldapsearch -H ldaps://host:636 -D "$BIND_DN" -w "$BIND_PASS" -b '' -s base
// non-zero exit means the credentials/DN are wrong regardless of WeKan settings

Type guard

const isBindError = (e) =>
  /invalid credentials|invalidCredential|ldap.*49|LDAPInvalidCredentials/i.test(e?.name || e?.reason || '');

Try / catch

try {
  const r = await Meteor.callAsync('ldap_test_connection');
} catch (e) {
  // e.error carries error.name, e.reason the message from bindIfNecessary
  if (isBindError(e)) {
    showError('Bind rejected by the directory: check LDAP_BIND_DN and LDAP_BIND_PASS.');
  }
}

Prevention

When it happens

Trigger: Meteor.call('ldap_test_connection') where the service bind fails: wrong LDAP_BIND_DN / LDAP_BIND_PASS, anonymous bind disallowed by the directory, expired/locked bind account, or the bind client timing out.

Common situations: Rotated service-account password not updated in WeKan; bind DN malformed (missing full DN, using UPN where DN required); password containing special characters mishandled; directory policy forbidding anonymous binds when no bind credentials configured.

Related errors


AI-assisted analysis of wekan/wekan@eb1433158b (2026-09-01). Data as JSON: /api/errors/624b980fa10b8745. Report an issue: GitHub.