Page MenuHomePhabricator

Some Diviner pages on secure.phabricator.com show "RuntimeException: strlen() expects parameter 1 to be string, array given"
Closed, ResolvedPublic

Description

Steps to reproduce:

  1. Go to https://secure.phabricator.com/book/phabdev/
  2. Go to "Custom Fields" section
  3. Click the first item called PhabricatorCustomField linking to https://secure.phabricator.com/book/phabdev/class/PhabricatorCustomField/

Expected outcome:

Great content!

Actual outcome:

Unhandled Exception ("RuntimeException")
strlen() expects parameter 1 to be string, array given

Reproducibility:

Always

Version:

The version currently deployed on https://secure.phabricator.com/

Additional information:

Same issue for some other linked pages, but not all of them. Random examples:

Event Timeline

Here's the full stack trace:

[2020-04-06 17:53:33] EXCEPTION: (RuntimeException) strlen() expects parameter 1 to be string, array given at [<arcanist>/src/error/PhutilErrorHandler.php:263]
arcanist(head=master, ref.master=32005f26a4e7), libcore(), phabricator(head=master, ref.master=f1d1ec3d77f1, custom=1), secure(head=master, ref.master=988cf9bd7958), services(head=master, ref.master=280ff19374b5)
  #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer, array) called at [<arcanist>/src/error/PhutilErrorHandler.php:263]
  #1 <#2> strlen(array) called at [<phabricator>/src/applications/diviner/controller/DivinerAtomController.php:438]
  #2 <#2> DivinerAtomController::composeTasks(DivinerLiveSymbol) called at [<phabricator>/src/applications/diviner/controller/DivinerAtomController.php:432]
  #3 <#2> DivinerAtomController::composeTasks(DivinerLiveSymbol) called at [<phabricator>/src/applications/diviner/controller/DivinerAtomController.php:132]
  #4 <#2> DivinerAtomController::handleRequest(AphrontRequest) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:286]
  #5 phlog(RuntimeException) called at [<phabricator>/src/aphront/handler/PhabricatorDefaultRequestExceptionHandler.php:41]
  #6 PhabricatorDefaultRequestExceptionHandler::handleRequestThrowable(AphrontRequest, RuntimeException) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:750]
  #7 AphrontApplicationConfiguration::handleThrowable(RuntimeException) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:298]
  #8 AphrontApplicationConfiguration::processRequest(AphrontRequest, PhutilDeferredLog, AphrontPHPHTTPSink, MultimeterControl) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:209]
  #9 AphrontApplicationConfiguration::runHTTPRequest(AphrontPHPHTTPSink) called at [<phabricator>/webroot/index.php:35]
epriestley triaged this task as Low priority.

Docblocks may have multiple copies of the same @attribute directive, like this:

@task config Configuring Things
@task internal Doing Internal Stuff

Long ago, this was returned from the API as a big block of text with newlines:

config Configuring Things
internal Doing Internal Stuff

Less long ago, but still long ago, this API changed to return a list:

array(
  "config Configuring Things"
  "internal Doing Internal Stuff",
);

When this change was made, I missed this callsite, and we started running strlen(array(...)), which isn't valid (it emits a warning and executes as strlen("Array")).

Recently, T13499 increased the severity of many warnings, including this one, causing the pages to fail.

The fix is to remove the strlen() call.

Separately, Diviner is in pretty rough shape. I'm hoping to give it some attention when T13410 moves forward.

I deployed D21061. First two example pages are good now, third one is hitting a different error. New trace is:

[2020-04-06 18:43:57] EXCEPTION: (RuntimeException) Invalid argument supplied for foreach() at [<arcanist>/src/error/PhutilErrorHandler.php:263]
arcanist(head=master, ref.master=33dc2fe8194d), libcore(), phabricator(head=master, ref.master=271e104c7ea4, custom=1), secure(head=master, ref.master=988cf9bd7958), services(head=master, ref.master=280ff19374b5)
  #0 <#2> PhutilErrorHandler::handleError(integer, string, string, integer, array) called at [<phabricator>/src/applications/diviner/controller/DivinerAtomController.php:439]
  #1 <#2> DivinerAtomController::composeTasks(DivinerLiveSymbol) called at [<phabricator>/src/applications/diviner/controller/DivinerAtomController.php:432]
  #2 <#2> DivinerAtomController::composeTasks(DivinerLiveSymbol) called at [<phabricator>/src/applications/diviner/controller/DivinerAtomController.php:132]
  #3 <#2> DivinerAtomController::handleRequest(AphrontRequest) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:286]
  #4 phlog(RuntimeException) called at [<phabricator>/src/aphront/handler/PhabricatorDefaultRequestExceptionHandler.php:41]
  #5 PhabricatorDefaultRequestExceptionHandler::handleRequestThrowable(AphrontRequest, RuntimeException) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:750]
  #6 AphrontApplicationConfiguration::handleThrowable(RuntimeException) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:298]
  #7 AphrontApplicationConfiguration::processRequest(AphrontRequest, PhutilDeferredLog, AphrontPHPHTTPSink, MultimeterControl) called at [<phabricator>/src/aphront/configuration/AphrontApplicationConfiguration.php:209]
  #8 AphrontApplicationConfiguration::runHTTPRequest(AphrontPHPHTTPSink) called at [<phabricator>/webroot/index.php:35]

This looks like a very similar issue.

The second issue is that the API still returns a string when there is exactly one @attribute of a given type. This is a bit goofy; PhutilExecChannel is another example case.

For now, I'm just going to clean up the fatal and not try to fix the systemic issue.

I deployed D21062, and the three examples in the original report look good now. I checked about a dozen other pages and couldn't find anything else broken; let me know if I missed anything. Thanks for the report!