symfony/routing · error · InvalidParameterException
Parameters for route
Error message
Parameters for route "%s" cannot contain a circular reference (in object of class "%s").
What it means
When serializing extra query parameters into the generated URL string, UrlGenerator casts nested objects to arrays using get_object_vars. If the same object appears twice (a circular reference / repeated object), an infinite recursion would occur, so InvalidParameterException is thrown naming the object's class.
Solutions
- Remove the circularly-referencing object from the parameters or clone the parts you need.
- Cast parameters to scalars/arrays explicitly before passing them (e.g. ->toArray() on the entity or DTO).
- Use an ID instead of the object reference in the query parameters.
Example fix
// before
$router->generate('list', ['q' => $entity]); // entity has circular relation
// after
$router->generate('list', ['q' => $entity->getId()]); Defensive patterns
Strategy: type-guard
Validate before calling
function hasCircular(array $params): bool {
$seen = [];
array_walk_recursive($params, function ($v) use (&$seen, &$has) { if (is_object($v)) { $id = spl_object_id($v); if (isset($seen[$id])) { $has = true; } $seen[$id] = true; } });
return $has ?? false;
} Type guard
function allScalars(array $params): bool {
$ok = true;
array_walk_recursive($params, function ($v) use (&$ok) { if (!is_scalar($v) && null !== $v) { $ok = false; } });
return $ok;
} Try / catch
try { $url = $router->generate($name, $params); } catch (\Symfony\Component\Routing\Exception\InvalidParameterException $e) { $url = $router->generate($name, array_map('strval', $scalarParams)); } Prevention
- Only pass scalars/null/flat arrays as query parameters.
- Convert entities/DTOs with ->toArray() or explicit field extraction before generate().
- Avoid passing objects with bidirectional relations into URL generation.
When it happens
Trigger: Passing a query parameter that references an object already passed (e.g. ['obj' => $o, 'nested' => ['o' => $o]]) or an object whose property graph is self-referential, when calling generate().
Common situations: Passing Doctrine entities with back-references (bidirectional relations) or models holding a parent pointer into generate()'s query array.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Parameter " " for route " " must match " " (" " given) to…
- Route aliases cannot be used on non-invokable class
- The " ()" method must not be called.
- The return value in config file
- Namespace " " is not a valid PSR-4 prefix.
AI-assisted analysis of symfony/routing@83fa223250 (2026-09-14).
Data as JSON: /api/errors/0136140351cd819d.
Report an issue: GitHub.
Appendix: source
Thrown at Generator/UrlGenerator.php:292
$schemeAuthority .= $host.$port;
}
}
if (self::RELATIVE_PATH === $referenceType) {
$url = self::getRelativePath($this->context->getPathInfo(), $url);
} else {
$url = $schemeAuthority.$this->context->getBaseUrl().$url;
}
// add a query string if needed
$extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, static fn ($a, $b) => $a == $b ? 0 : 1);
$extra = array_replace($defaultQuery, $extra, $queryParameters);
$seen = [];
array_walk_recursive($extra, $caster = static function (&$v) use (&$caster, &$seen, $name) {
if (\is_object($v)) {
if (isset($seen[$id = spl_object_id($v)])) {
throw new InvalidParameterException(\sprintf('Parameters for route "%s" cannot contain a circular reference (in object of class "%s").', $name, get_debug_type($v)));
}
if ($vars = get_object_vars($v)) {
$seen[$id] = true;
array_walk_recursive($vars, $caster);
unset($seen[$id]);
$v = $vars;
} elseif ($v instanceof \Stringable) {
$v = (string) $v;
} else {
$v = [];
}
}
});
// extract fragment
$fragment = $defaults['_fragment'] ?? '';
if (isset($extra['_fragment'])) {View on GitHub (pinned to 83fa223250)