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

  1. Instantiate the extender inline with `new` at the start of the chain: (new SomeExtender())->method(...)
  2. If wrapped in a helper, inline the new expression or register support for it in the PHPStan extension.
  3. Check Resolver.php's resolveExtender path to see which expression shapes are supported.
  4. 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

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


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)