phacility/phabricator · error · Exception
You must pass the user to %s.
Error message
You must pass the user to %s.
What it means
AphrontFormView::render() requires the acting user because phabricator_form() embeds viewer-dependent session/CSRF metadata into the form markup. render() calls hasViewer(), inherited from AphrontView, and throws when no viewer was ever set with setUser()/setViewer(). The check fires at render time, typically deep inside a page, dialog, or controller response.
Source
Thrown at src/view/form/AphrontFormView.php:138
* controls. It will propagate some information from the form to the
* control to simplify rendering.
*
* @param AphrontFormControl Control to append.
* @return this
*/
public function appendControl(AphrontFormControl $control) {
$this->controls[] = $control;
return $this->appendChild($control);
}
public function render() {
require_celerity_resource('phui-form-view-css');
$layout = $this->buildLayoutView();
if (!$this->hasViewer()) {
throw new Exception(
pht(
'You must pass the user to %s.',
__CLASS__));
}
$sigils = $this->sigils;
if ($this->workflow) {
$sigils[] = 'workflow';
}
return phabricator_form(
$this->getViewer(),
array(
'class' => implode(' ', $this->classes),
'action' => $this->action,
'method' => $this->method,
'enctype' => $this->encType,
'sigil' => $sigils ? implode(' ', $sigils) : null,View on GitHub (pinned to 5720a38cfe)
Solutions
- Call $form->setUser($viewer) (or setViewer($viewer)) immediately after constructing the form.
- In controllers, always pass $this->getViewer().
- For non-request contexts, load and pass an explicit acting PhabricatorUser before rendering.
Example fix
// before $form = id(new AphrontFormView()) ->appendChild($control); // no user set; render() throws // after $form = id(new AphrontFormView()) ->setUser($viewer) ->appendControl($control);
Defensive patterns
Strategy: validation
Validate before calling
if (!$form->hasViewer()) {
$form->setUser($viewer);
}
$html = $form->render(); Prevention
- Make setUser($viewer) the first fluent call on every AphrontFormView.
- hasViewer() is public on every AphrontView — assert it in shared render pipelines.
- In controllers, always source the viewer from $this->getViewer().
When it happens
Trigger: Building an AphrontFormView in a controller, dialog, or standalone script and rendering it without ever calling $form->setUser($viewer) (or setViewer($viewer)).
Common situations: A new custom form where the setUser() line was forgotten; rendering forms from CLI scripts, daemons, or mail generation where no viewer exists; refactors that restructure form builders and drop the user assignment.
Related errors
- Call %s when rendering an action as a form.
- You must set a datasource to use a TokenizerControl.
- Call %s before rendering tokenizers. Use %s on %s to do this
- Service "%s" is unrecognized, restricted, or you do not have
- When creating a new Almanac interface via the Conduit API, y
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/da522eb517a81902.
Report an issue: GitHub.