{"record":{"id":"da294901e297f445","repo":"phacility/phabricator","slug":"you-must-call-s-when-rendering-an-s","errorCode":null,"errorMessage":"You must call %s when rendering an %s.","messagePattern":"You must call (.+?) when rendering an (.+?)\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/view/AphrontDialogView.php","lineNumber":295,"sourceCode":"      $meta = array();\n      if ($this->disableWorkflowOnCancel) {\n        $meta['disableWorkflow'] = true;\n      }\n\n      $buttons[] = javelin_tag(\n        'a',\n        array(\n          'href'  => $this->cancelURI,\n          'class' => 'button button-grey',\n          'name'  => '__cancel__',\n          'sigil' => 'jx-workflow-button',\n          'meta' => $meta,\n        ),\n        $this->cancelText);\n    }\n\n    if (!$this->hasViewer()) {\n      throw new Exception(\n        pht(\n          'You must call %s when rendering an %s.',\n          'setViewer()',\n          __CLASS__));\n    }\n\n    $classes = array();\n    $classes[] = 'aphront-dialog-view';\n    $classes[] = $this->class;\n    if ($this->flush) {\n      $classes[] = 'aphront-dialog-flush';\n    }\n\n    switch ($this->width) {\n      case self::WIDTH_FORM:\n      case self::WIDTH_FULL:\n        $classes[] = 'aphront-dialog-view-width-'.$this->width;\n        break;","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/view/AphrontDialogView.php#L277-L313","documentation":"Modern Phabricator views require an acting viewer (the logged-in PhabricatorUser) before rendering, because policies, links, and rendering all depend on who is looking. AphrontDialogView::render() enforces this by checking hasViewer() and throwing if render() is reached without a prior setViewer() call. It is a programming error in the calling controller or view, not a runtime data problem.","triggerScenarios":"Building an AphrontDialogView in a controller/handler and returning it (or calling render()) without '$dialog->setViewer($viewer)' first. Typical with ported pre-viewer-era code, dialogs created inside helper methods that never receive the viewer, or dialogs constructed in CLI/AJAX contexts where no viewer was resolved from the request.","commonSituations":"Upgrading old Phabricator code or extensions written before views required viewers; copy-pasting dialog code from another controller and dropping the setViewer line; rendering a dialog from a workflow handler where $request->getViewer() was never fetched.","solutions":["Call '$dialog->setViewer($this->getViewer())' (in a PhabricatorController) or '$dialog->setViewer($request->getViewer())' before producing the response.","If the dialog is built in a helper, pass the viewer in and set it there, so every construction path is covered.","Set the viewer immediately after constructing the view so later refactors cannot drop it.","Search for other view constructions in the same code path — the same omission usually repeats."],"exampleFix":"// before\npublic function handleRequest(AphrontRequest $request) {\n  $dialog = id(new AphrontDialogView())\n    ->setTitle(pht('Delete widget'))\n    ->addCancelButton('/w/');\n  return id(new AphrontResponse())->setContent($dialog->render());\n}\n\n// after\npublic function handleRequest(AphrontRequest $request) {\n  $viewer = $this->getViewer();\n  $dialog = id(new AphrontDialogView())\n    ->setViewer($viewer)\n    ->setTitle(pht('Delete widget'))\n    ->addCancelButton('/w/');\n  return id(new AphrontResponse())->setContent($dialog->render());\n}","handlingStrategy":"validation","validationCode":"// Always resolve and set the viewer as the first step of dialog construction:\n$viewer = $request->getViewer(); // or $this->getViewer() inside a controller\n$dialog = id(new AphrontDialogView())\n  ->setViewer($viewer)           // set immediately, before any content\n  ->setTitle($title);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make setViewer() the first call in every view-construction chain so refactors cannot drop it.","In helpers that build dialogs, require the viewer as a parameter instead of constructing views viewer-less.","When porting old extensions, search for 'new AphrontDialogView()' and add setViewer() to each site."],"tags":["phabricator","ui","views","rendering","php"],"backgroundTag":"view-missing-required-state","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}