phacility/phabricator · error · Exception
Curtain extension ("%s", of class "%s") did not return a lis
Error message
Curtain extension ("%s", of class "%s") did not return a list of curtain panels from method "%s". This method must return an array, and each value in the array must be a "%s" object. What it means
PHUICurtainExtension::buildCurtainPanels($object) must return an array of PHUICurtainPanelView objects — an empty array when the extension has nothing to show. buildExtensionPanels() validates the return value: if the method returns a single panel object, null, or any other non-array, this exception is thrown during page rendering.
Source
Thrown at src/view/extension/PHUICurtainExtension.php:91
$viewer);
if (!$has_application) {
unset($extensions[$key]);
}
}
foreach ($extensions as $key => $extension) {
if (!$extension->shouldEnableForObject($object)) {
unset($extensions[$key]);
}
}
$result = array();
foreach ($extensions as $key => $extension) {
$panels = $extension->buildCurtainPanels($object);
if (!is_array($panels)) {
throw new Exception(
pht(
'Curtain extension ("%s", of class "%s") did not return a list of '.
'curtain panels from method "%s". This method must return an '.
'array, and each value in the array must be a "%s" object.',
$key,
get_class($extension),
'buildCurtainPanels()',
'PHUICurtainPanelView'));
}
foreach ($panels as $panel_key => $panel) {
if (!($panel instanceof PHUICurtainPanelView)) {
throw new Exception(
pht(
'Curtain extension ("%s", of class "%s") returned a list of '.
'curtain panels from "%s" that contains an invalid value: '.
'a value (with key "%s") is not an object of class "%s". '.
'Each item in the returned array must be a panel.',View on GitHub (pinned to 5720a38cfe)
Solutions
- Wrap single panels in an array: return array($panel);
- Make 'return array();' the unconditional last line, and convert guard clauses to return empty arrays.
- Keep panel construction in a helper and always return array($this->buildPanel($object)).
Example fix
// before
public function buildCurtainPanels($object) {
if (!$this->shouldShow($object)) {
return; // null: throws
}
return $this->buildPanel($object); // single object: throws
}
// after
public function buildCurtainPanels($object) {
if (!$this->shouldShow($object)) {
return array();
}
return array(
$this->buildPanel($object),
);
} Defensive patterns
Strategy: type-guard
Validate before calling
$panels = $extension->buildCurtainPanels($object);
if (!is_array($panels)) {
// contract violation: fix before rendering in production
phlog(pht('%s returned a non-array from buildCurtainPanels().', get_class($extension)));
} Type guard
function returnsPanelArray(PHUICurtainExtension $extension, $object) {
return is_array($extension->buildCurtainPanels($object));
} Prevention
- Make 'return array();' the unconditional last line of buildCurtainPanels().
- Guard clauses must 'return array();' too, never a bare 'return;'.
- Unit test each extension against a representative object.
When it happens
Trigger: An extension buildCurtainPanels() does 'return $panel;' (single object), 'return;' (null on an early exit), or returns a rendered string or PHUIInfoView instead of an array.
Common situations: A first extension with exactly one panel returned directly; early-return guard clauses added during refactoring; copy-paste from render()-style methods that return views rather than panel lists.
Related errors
- View '%s' did not return an array from getTagAttributes()!
- Curtain extension ("%s", of class "%s") did not return an ap
- Curtain extension ("%s", of class "%s") returned a list of c
- You must set the %s to render a %s.
- 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/1f507b645bc7bc81.
Report an issue: GitHub.