passbolt/passbolt_api · error · InvalidArgumentException

Using callbacks for userCustomFilter is not supported…

Error message

Using callbacks for userCustomFilter is not supported anymore. Please use LDAP search filter instead.

What it means

DirectorySync's LDAP user query customization no longer accepts PHP callable filters. When the stored userCustomFilter setting is a callable, _customizeUsersQuery throws this InvalidArgumentException to force migration to standard LDAP search filter strings, which are parsed and applied as raw filters on the LDAP query builder.

Solutions

  1. Replace the callable userCustomFilter with an equivalent LDAP search filter string, e.g. '(objectClass=user)', stored via the directory sync settings
  2. Remove any code that sets userCustomFilter as a Closure/callable
  3. Test the new filter string with the LDAP provider before re-enabling sync

Example fix

// before
$settings->setUserCustomFilters(function (Builder $query) { $query->where([' Department' => 'IT']); });
// after
$settings->setUserCustomFilters('(department=IT)');
Defensive patterns

Strategy: validation

Validate before calling

$filter = $this->directorySettings->getUserCustomFilters();
if (is_callable($filter)) {
    throw new RuntimeException('userCustomFilter must be an LDAP filter string, not a callback');
}

Type guard

$filter = is_string($customFilter) ? $customFilter : null;

Prevention

When it happens

Trigger: Calling _fetchAndInitializeUsersQuery (user LDAP lookup) when directorySettings->getUserCustomFilters() returns a callable — i.e., the org settings or custom plugin registered a callback-based filter.

Common situations: Upgrading passbolt DirectorySync from an old version where callback filters were allowed; a custom integration still defining userCustomFilter as a closure in directory settings code.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/c9292b61916255a4. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/DirectorySync/src/Utility/LdapDirectory.php:552

    {
        $directoryResults = $this->getFilteredDirectoryResults();

        return $directoryResults->getGroupsAsArray();
    }

    /**
     * Customize users query as per configuration (if available).
     *
     * @param \LdapRecord\Query\Builder $query query
     * @return \LdapRecord\Query\Builder
     * @throws \InvalidArgumentException If userCustomFilter callback is used.
     * @throws \InvalidArgumentException If userCustomFilter cannot be parsed.
     */
    private function _customizeUsersQuery(Builder $query): Builder
    {
        $userCustomFilter = $this->directorySettings->getUserCustomFilters();
        if (is_callable($userCustomFilter)) {
            throw new InvalidArgumentException(
                'Using callbacks for userCustomFilter is not supported anymore. Please use LDAP search filter instead.'
            );
        } elseif (is_string($userCustomFilter)) {
            try {
                $filter = Parser::parse($userCustomFilter);
                $query->rawFilter(Parser::assemble($filter));
            } catch (ParserException $pe) {
                throw new InvalidArgumentException(
                    'An error has occurred parsing userCustomFilter: ' . $pe->getMessage()
                );
            }
        }

        return $query;
    }

    /**
     * Customize groups query as per configuration (if available).

View on GitHub (pinned to 31c1bbc10f)