symfony/finder · error · InvalidArgumentException
Invalid PHP callback.
Error message
Invalid PHP callback.
What it means
ExcludeDirectoryFilterIterator treats each entry of $directories as either a directory name string or a prune filter callable; when an entry is neither a string nor callable it throws InvalidArgumentException('Invalid PHP callback.'). This occurs while building the exclusion rules in the constructor.
Solutions
- Pass only strings (directory names) or valid callables; flatten the array
- Coerce non-string values to strings with (string) or validate each with is_string($d) || is_callable($d) beforehand
- Fix config deserialization that injects numeric keys or objects into the exclusion list
Example fix
// before $finder->exclude([0 => 'vendor', 'cache' => true]); // 'true' boolean entry // after $finder->exclude(['vendor', 'cache']);
Defensive patterns
Strategy: type-guard
Validate before calling
foreach ($dirs as $d) { if (!is_string($d) && !is_callable($d)) { throw new \InvalidArgumentException('Exclusion must be a string or callable'); } } Type guard
function isValidExclusion(mixed $d): bool { return is_string($d) || is_callable($d); } Try / catch
try { $finder->exclude($dirs); } catch (\InvalidArgumentException $e) { /* handle invalid exclusion entry */ } Prevention
- Pass only directory-name strings or callables to Finder::exclude()
- Flatten nested arrays and cast scalars to strings before excluding
- Validate config-derived exclusion lists with array_filter($dirs, 'is_string')
When it happens
Trigger: Finder::exclude([123, ['not-callable-array'], new \stdClass()]) — passing integers, non-invokable objects, or arrays that aren't valid callables as exclusion entries.
Common situations: Config files listing exclusions with numeric or mixed values, dynamic exclusion lists built from unvalidated input, accidentally passing a nested array of names instead of flat strings.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- Invalid PHP callback.
- Invalid operator " ".
- Don't understand " " as a number test.
- Invalid number " ".
- The SortableIterator takes a PHP callable or a valid…
AI-assisted analysis of symfony/finder@4d6c057bfd (2026-09-13).
Data as JSON: /api/errors/9d853de3de098319.
Report an issue: GitHub.
Appendix: source
Thrown at Iterator/ExcludeDirectoryFilterIterator.php:50
private ?string $excludedPattern = null;
private ?string $excludedRootPattern = null;
/** @var list<callable(SplFileInfo):bool> */
private array $pruneFilters = [];
/**
* @param \Iterator<string, SplFileInfo> $iterator The Iterator to filter
* @param list<string|callable(SplFileInfo):bool> $directories An array of directories to exclude
*/
public function __construct(\Iterator $iterator, array $directories)
{
$this->iterator = $iterator;
$this->isRecursive = $iterator instanceof \RecursiveIterator;
$patterns = [];
$rootPatterns = [];
foreach ($directories as $directory) {
if (!\is_string($directory)) {
if (!\is_callable($directory)) {
throw new \InvalidArgumentException('Invalid PHP callback.');
}
$this->pruneFilters[] = $directory;
continue;
}
$directory = rtrim($directory, '/');
if (str_starts_with($directory, '/')) {
$rootPatterns[] = preg_quote(substr($directory, 1), '#');
} elseif (!$this->isRecursive || str_contains($directory, '/')) {
$patterns[] = preg_quote($directory, '#');
} else {
$this->excludedDirs[$directory] = true;
}
}
if ($patterns) {
$this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';View on GitHub (pinned to 4d6c057bfd)