{"record":{"id":"a3c92b356a1e686a","repo":"phacility/phabricator","slug":"buildkite-did-not-return-a-s","errorCode":null,"errorMessage":"Buildkite did not return a \"%s\"!","messagePattern":"Buildkite did not return a \"(.+?)\"!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php","lineNumber":175,"sourceCode":"\n    $this->resolveFutures(\n      $build,\n      $build_target,\n      array($future));\n\n    $this->logHTTPResponse($build, $build_target, $future, pht('Buildkite'));\n\n    list($status, $body) = $future->resolve();\n    if ($status->isError()) {\n      throw new HarbormasterBuildFailureException();\n    }\n\n    $response = phutil_json_decode($body);\n\n    $uri_key = 'web_url';\n    $build_uri = idx($response, $uri_key);\n    if (!$build_uri) {\n      throw new Exception(\n        pht(\n          'Buildkite did not return a \"%s\"!',\n          $uri_key));\n    }\n\n    $target_phid = $build_target->getPHID();\n\n    $api_method = 'harbormaster.createartifact';\n    $api_params = array(\n      'buildTargetPHID' => $target_phid,\n      'artifactType' => HarbormasterURIArtifact::ARTIFACTCONST,\n      'artifactKey' => 'buildkite.uri',\n      'artifactData' => array(\n        'uri' => $build_uri,\n        'name' => pht('View in Buildkite'),\n        'ui.external' => true,\n      ),\n    );","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php#L157-L193","documentation":"After POSTing to Buildkite's create-build endpoint and receiving a non-error status, the step decodes the JSON response and requires a web_url key, which becomes the URI artifact linking to the created Buildkite build. If the decoded payload lacks web_url (API behavior change, or an unexpected 2xx payload), the step throws and the build fails. The full HTTP response is logged to the build log first, so the payload can be inspected.","triggerScenarios":"Buildkite returning a success status with a payload that has no web_url field (API drift); a proxy or middleware rewriting the response body while preserving the status code.","commonSituations":"Buildkite API changes after a long-lived integration; exotic proxy setups that alter response bodies. Rare in practice.","solutions":["Inspect the logged HTTP response on the failed target to see exactly what Buildkite returned","Retry the build once: transient API anomalies usually do not repeat","If Buildkite permanently changed the field, update Phabricator/the step so $uri_key matches the new response shape"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  // execute the Buildkite step\n} catch (HarbormasterBuildFailureException $ex) {\n  // expected failure path (e.g. HTTP error status): mark target failed, no retry\n} catch (Exception $ex) {\n  // unexpected payload (e.g. missing web_url): log and retry the build once\n}","preventionTips":["Keep Phabricator updated so response parsing tracks Buildkite API changes","Check the logged HTTP response on the failed target to distinguish payload drift from transient faults","Monitor Buildkite API status before investigating local configuration"],"tags":["harbormaster","phabricator","buildkite","api-response","json"],"backgroundTag":"unexpected-api-response","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}