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
- Replace the callable userCustomFilter with an equivalent LDAP search filter string, e.g. '(objectClass=user)', stored via the directory sync settings
- Remove any code that sets userCustomFilter as a Closure/callable
- 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
- Always define custom LDAP filters as filter strings, never closures
- After upgrading DirectorySync, grep configuration for setUserCustomFilters callbacks
- Document the filter format in your deployment config
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
- Using callbacks for groupCustomFilter is not supported…
- An error has occurred parsing groupCustomFilter
- An error has occurred parsing userCustomFilter
- The ldap integration is not configured or it is disabled
- group(s) returned by your directory are invalid and will be…
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)