Page MenuHomePhorge

PhabricatorDataNotAttachedException when rendering project hovercard with username mentioned in project description
Closed, ResolvedPublic

Description

Steps to reproduce:

  1. PHP 8.2.17; Phorge at 328aee033fbdc704620e2facae4aa68b836217bb
  2. Make sure rPd5a28e12a005e7082dab685dd6e615da5213db33 from T15275 is deployed.
  3. Set up a project tag project which includes a username mention @username in its project description and that user is not the currently logged in user.
  4. In a task comment, write the project tag #project.
  5. Hover over the project tag.
[2024-03-21 22:33:27] EXCEPTION: (PhabricatorDataNotAttachedException) Attempting to access attached data on PhabricatorProject, but the data is not actually attached. Before accessing attachable data on an object, you must load and attach it.

Data is normally attached by calling the corresponding needX() method on the Query class when the object is loaded. You can also call the corresponding attachX() method explicitly. at [<phorge>/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php:283]
arcanist(head=master, ref.master=174bf094ef9f), phorge(head=master, ref.master=d42b3eb0b17a)
  #0 <#2> PhabricatorLiskDAO::assertAttachedKey(array, string) called at [<phorge>/src/applications/project/storage/PhabricatorProject.php:210]
  #1 <#2> PhabricatorProject::isUserMember(string) called at [<phorge>/src/applications/project/storage/PhabricatorProject.php:147]
  #2 <#2> PhabricatorProject::hasAutomaticCapability(string, PhabricatorUser) called at [<phorge>/src/applications/policy/filter/PhabricatorPolicyFilter.php:539]
  #3 <#2> PhabricatorPolicyFilter::checkCapability(PhabricatorProject, string) called at [<phorge>/src/applications/policy/filter/PhabricatorPolicyFilter.php:268]
  #4 <#2> PhabricatorPolicyFilter::apply(array) called at [<phorge>/src/applications/policy/filter/PhabricatorPolicyFilterSet.php:93]
  #5 <#2> PhabricatorPolicyFilterSet::resolveCapabilities() called at [<phorge>/src/applications/policy/filter/PhabricatorPolicyFilterSet.php:54]
  #6 <#2> PhabricatorPolicyFilterSet::hasCapability(PhabricatorUser, PhabricatorProject, string) called at [<phorge>/src/applications/people/markup/PhabricatorMentionRemarkupRule.php:116]
  #7 <#2> PhabricatorMentionRemarkupRule::didMarkupText() called at [<phorge>/src/infrastructure/markup/remarkup/PhutilRemarkupEngine.php:362]
  #8 <#2> PhutilRemarkupEngine::postprocessText(array) called at [<phorge>/src/infrastructure/markup/PhabricatorMarkupEngine.php:164]
  #9 <#2> PhabricatorMarkupEngine::execute() called at [<phorge>/src/infrastructure/markup/PhabricatorMarkupEngine.php:111]
  #10 <#2> PhabricatorMarkupEngine::process() called at [<phorge>/src/infrastructure/markup/PhabricatorMarkupEngine.php:75]
  #11 <#2> PhabricatorMarkupEngine::renderOneObject(PhabricatorMarkupOneOff, string, PhabricatorUser, PhabricatorProject) called at [<phorge>/src/infrastructure/markup/view/PHUIRemarkupView.php:86]
  #12 <#2> phutil_tag(string, array, PHUIRemarkupView) called at [<phorge>/src/applications/project/view/PhabricatorProjectCardView.php:86]
  #13 <#2> PhabricatorProjectCardView::getTagContent() called at [<phorge>/src/view/AphrontTagView.php:161]
  #14 <#2> phutil_escape_html(PhabricatorProjectCardView) called at [<phorge>/src/infrastructure/markup/render.php:139]
  #15 <#2> phutil_escape_html(array) called at [<phorge>/src/infrastructure/markup/render.php:97]
  #16 <#2> phutil_tag(string, array, array) called at [<phorge>/src/infrastructure/javelin/markup.php:70]
  #17 <#2> javelin_tag(string, array, array) called at [<phorge>/src/view/AphrontTagView.php:158]
  #18 <#2> AphrontTagView::render() called at [<phorge>/src/view/AphrontView.php:222]
  #19 <#2> AphrontView::producePhutilSafeHTML() called at [<phorge>/src/infrastructure/markup/render.php:115]
  #20 <#2> phutil_escape_html(PHUIHovercardView)
  #21 <#2> array_map(string, array) called at [<phorge>/src/infrastructure/markup/render.php:185]
  #22 <#2> hsprintf(string, PHUIHovercardView) called at [<phorge>/src/aphront/response/AphrontResponse.php:326]
  #23 <#2> AphrontResponse::processValueForJSONEncoding(PHUIHovercardView, string)
  #24 <#2> array_walk_recursive(array, array) called at [<phorge>/src/aphront/response/AphrontResponse.php:340]
  #25 <#2> AphrontResponse::encodeJSONForHTTPResponse(array) called at [<phorge>/src/aphront/response/AphrontAjaxResponse.php:58]
  #26 <#2> AphrontAjaxResponse::buildResponseString() called at [<phorge>/src/aphront/response/AphrontResponse.php:70]
  #27 <#2> AphrontResponse::getContentIterator() called at [<phorge>/src/aphront/sink/AphrontHTTPSink.php:112]
  #28 <#2> AphrontHTTPSink::writeResponse(AphrontAjaxResponse) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:380]
  #29 <#2> AphrontApplicationConfiguration::writeResponse(AphrontPHPHTTPSink, AphrontAjaxResponse) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:303]
  #30 phlog(PhabricatorDataNotAttachedException) called at [<phorge>/src/aphront/handler/PhabricatorAjaxRequestExceptionHandler.php:27]
  #31 PhabricatorAjaxRequestExceptionHandler::handleRequestThrowable(AphrontRequest, PhabricatorDataNotAttachedException) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:751]
  #32 AphrontApplicationConfiguration::handleThrowable(PhabricatorDataNotAttachedException) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:337]
  #33 AphrontApplicationConfiguration::processRequest(AphrontRequest, PhutilDeferredLog, AphrontPHPHTTPSink, MultimeterControl) called at [<phorge>/src/aphront/configuration/AphrontApplicationConfiguration.php:203]
  #34 AphrontApplicationConfiguration::runHTTPRequest(AphrontPHPHTTPSink) called at [<phorge>/webroot/index.php:35]

This problem does not happen when backing out https://we.phorge.it/rPd5a28e12a005e7082dab685dd6e615da5213db33

Upstreamed from https://phabricator.wikimedia.org/T360530

Event Timeline

Also note that we have a similar PhabricatorDataNotAttachedException in PhabricatorRepositoryCommit (via getRepository()) in downstream https://phabricator.wikimedia.org/T360714. It's without reproduction steps but sounds a bit similar.

So this is quite an edge-case:

  • PhabricatorMentionRemarkupRule wants to give the mention a different color, depending on if the user can view the "context object", in this case the Project.
  • There's an automatic rule, saying a member of a project can always view the project
  • When loading the project for the hovercard, we don't bother loading all the member list
  • When loading the user for the mention, we don't bother loading all its projects
  • so data is not available at the rendering point.

I expect this to show up in some other cases where a user is mentioned on an object that has policy, but there might already be some handling of that in the standard Policy pipeline (Loading needed project membership edges).
I'll try to see if whatever we do in the pipeline can be done here too.


I don't think it's the same thing as the downstream issue, because the trace there doesn't include Remakrup or PhabricatorUser.

It might not happen on any other card, because we might not be rendering Remarkup on any other card. Interesting....