flarum/framework · error · Exception
Unable to resolve extender for '.$value->var::class
Error message
Unable to resolve extender for '.$value->var::class
What it means
This is part of Flarum's PHPStan extension, which rewrites extender calls in static analysis. resolveExtender() walks a method-call chain to its base expression; if the base expression's variable is not a `new` expression (an instantiated extender object), it cannot determine which extender applies and throws this Exception with the AST node class name for debugging.
Solutions
- Instantiate the extender inline with `new` at the start of the chain: (new SomeExtender())->method(...)
- If wrapped in a helper, inline the new expression or register support for it in the PHPStan extension.
- Check Resolver.php's resolveExtender path to see which expression shapes are supported.
- Report/add a case in the extension if a legitimately supported pattern is misdetected.
Example fix
// before $extender = $this->getExtender(); // factory/container lookup $extender->extend($extension); // after (new SomeExtender())->extend($extension);
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the extender chain starts with a new expression before analysis tooling processes it: assert($extender instanceof SomeExtender); $extender->extend($extension);
Type guard
function isInlineExtender(mixed $expr): bool {
return $expr instanceof PhpParser\Node\Expr\New_;
} Try / catch
try {
$extender = $resolver->resolveExtendersFromArray([$stmt]);
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'Unable to resolve extender')) {
return null; // skip unsupported expression shape
}
throw $e;
} Prevention
- Always write extender chains starting with `new ExtenderClass()` inline.
- Avoid wrapping extenders in factory functions when using Flarum's PHPStan extension.
- Keep custom extenders aligned with the shapes supported by the extension.
When it happens
Trigger: Static analysis code that chains methods on something other than a directly-instantiated extender — e.g. calling methods on a variable assigned from a function return value, a property, or a container lookup instead of `new SomeExtender()...`, which resolveExtenderNew() requires.
Common situations: Refactoring extenders into factory functions or container-resolved services so the expression no longer starts with `new`; assigning an extender to a variable in a way the PHPStan extension cannot trace back to a New_ node; using an unsupported extender pattern in analyzed code.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unknown relationship type for relation
- Route $name already exists
- Could not generate URL for route '$routeName': no value…
- Route $name not found
- Both text and html views must be provided to send an email…
AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15).
Data as JSON: /api/errors/7d094e5691943875.
Report an issue: GitHub.
Appendix: source
Thrown at php-packages/phpstan/src/Extender/Resolver.php:212
$arg->value->setAttributes([]);
return $arg->value;
}, $var->args));
}
private function resolveExtender(MethodCall $value): Extender
{
$methodStack = [$this->resolveMethod($value)];
while ($value->var instanceof MethodCall) {
$methodStack[] = $this->resolveMethod($value->var);
$value = $value->var;
}
$methodStack = array_reverse($methodStack);
if (! $value->var instanceof New_) {
throw new \Exception('Unable to resolve extender for '.$value->var::class);
}
return $this->resolveExtenderNew($value->var, $methodStack);
}
}
View on GitHub (pinned to 4b939f6853)