diff --git a/ldap/search.go b/ldap/search.go
index 872f6fec3fdb2a8516f7e3da55dddeb972b358f5..db29ba092ea0cb1e1be3db3a753c75c7e1188f3f 100644
--- a/ldap/search.go
+++ b/ldap/search.go
@@ -10,16 +10,24 @@ import (
 	"git.autistici.org/ai3/go-common/clientutil"
 )
 
-// Treat all errors as potential network-level issues, except for a
-// whitelist of LDAP protocol level errors that we know are benign.
+// Interface matched by net.Error.
+type hasTemporary interface {
+	Temporary() bool
+}
+
+// Treat network errors as temporary. Other errors are permanent by
+// default.
 func isTemporaryLDAPError(err error) bool {
-	ldapErr, ok := err.(*ldap.Error)
-	if !ok {
-		return true
-	}
-	switch ldapErr.ResultCode {
-	case ldap.ErrorNetwork:
-		return true
+	switch v := err.(type) {
+	case *ldap.Error:
+		switch v.ResultCode {
+		case ldap.ErrorNetwork:
+			return true
+		default:
+			return false
+		}
+	case hasTemporary:
+		return v.Temporary()
 	default:
 		return false
 	}
@@ -32,6 +40,7 @@ func (p *ConnectionPool) Search(ctx context.Context, searchRequest *ldap.SearchR
 	err := clientutil.Retry(func() error {
 		conn, err := p.Get(ctx)
 		if err != nil {
+			// Here conn is nil, so we don't need to Release it.
 			if isTemporaryLDAPError(err) {
 				return clientutil.TempError(err)
 			}
@@ -44,7 +53,7 @@ func (p *ConnectionPool) Search(ctx context.Context, searchRequest *ldap.SearchR
 
 		result, err = conn.Search(searchRequest)
 		if err != nil && isTemporaryLDAPError(err) {
-			p.Release(conn, nil)
+			p.Release(conn, err)
 			return clientutil.TempError(err)
 		}
 		p.Release(conn, err)