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

  1. Implement getExtensionApplication() to return a real instance, e.g. return new PhabricatorManiphestApplication();
  2. Verify the returned class is a concrete PhabricatorApplication subclass that exists and is enabled.
  3. 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

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


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/269741c14d056060. Report an issue: GitHub.