phacility/phabricator · error · Exception
Curtain extension ("%s", of class "%s") did not return an ap
Error message
Curtain extension ("%s", of class "%s") did not return an application from method "%s". This method must return an object of class "%s". What it means
Every PHUICurtainExtension subclass must implement getExtensionApplication() and return the PhabricatorApplication it belongs to. PHUICurtainExtension::buildExtensionPanels() uses that object to test whether the application is installed and visible for the current viewer before building any curtain panels. If the method returns null, a class-name string, or any non-PhabricatorApplication value, this exception is thrown on every page render that builds curtains.
Source
Thrown at src/view/extension/PHUICurtainExtension.php:60
}
protected function newPanel() {
return new PHUICurtainPanelView();
}
final public static function buildExtensionPanels(
PhabricatorUser $viewer,
$object) {
$extensions = self::getAllExtensions();
foreach ($extensions as $extension) {
$extension->setViewer($viewer);
}
foreach ($extensions as $key => $extension) {
$application = $extension->getExtensionApplication();
if (!($application instanceof PhabricatorApplication)) {
throw new Exception(
pht(
'Curtain extension ("%s", of class "%s") did not return an '.
'application from method "%s". This method must return an '.
'object of class "%s".',
$key,
get_class($extension),
'getExtensionApplication()',
'PhabricatorApplication'));
}
$has_application = PhabricatorApplication::isClassInstalledForViewer(
get_class($application),
$viewer);
if (!$has_application) {
unset($extensions[$key]);
}
}View on GitHub (pinned to 5720a38cfe)
Solutions
- Implement getExtensionApplication() to return a real instance, e.g. return new PhabricatorManiphestApplication();
- Verify the returned class is a concrete PhabricatorApplication subclass that exists and is enabled.
- Add a unit test that calls PHUICurtainExtension::buildExtensionPanels($viewer, $object) so contract violations fail in CI.
Example fix
// before
public function getExtensionApplication() {
return null; // or 'PhabricatorManiphestApplication'
}
// after
public function getExtensionApplication() {
return new PhabricatorManiphestApplication();
} Defensive patterns
Strategy: type-guard
Validate before calling
$app = $extension->getExtensionApplication();
if (!($app instanceof PhabricatorApplication)) {
// contract violation: fix the extension before it renders in production
phlog(pht('Bad getExtensionApplication() in %s', get_class($extension)));
} Type guard
function isValidCurtainExtension(PHUICurtainExtension $extension) {
return $extension->getExtensionApplication()
instanceof PhabricatorApplication;
} Prevention
- Model new extensions on core ones (e.g. Maniphest curtain extensions) that return a real application object.
- Never return a class-name string or null from getExtensionApplication().
- Run buildExtensionPanels() in a unit test for each custom extension.
When it happens
Trigger: A custom curtain extension implements buildCurtainPanels() but leaves getExtensionApplication() returning null; or returns the string 'PhabricatorManiphestApplication' instead of an application instance; or returns the result of a lookup that can be null.
Common situations: Writing a first custom extension by copying only the panel-building half from a core extension; refactoring or renaming an application class so the returned class no longer exists; fork updates that change application constructors.
Related errors
- Curtain extension ("%s", of class "%s") did not return a lis
- Method '%s' belongs to application '%s', which is not instal
- View '%s' did not return an array from getTagAttributes()!
- Curtain extension ("%s", of class "%s") returned a list of c
- Service "%s" is unrecognized, restricted, or you do not have
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/269741c14d056060.
Report an issue: GitHub.