phacility/phabricator · error · Exception

Buildkite did not return a "%s"!

Error message

Buildkite did not return a "%s"!

What it means

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.

Source

Thrown at src/applications/harbormaster/step/HarbormasterBuildkiteBuildStepImplementation.php:175

    $this->resolveFutures(
      $build,
      $build_target,
      array($future));

    $this->logHTTPResponse($build, $build_target, $future, pht('Buildkite'));

    list($status, $body) = $future->resolve();
    if ($status->isError()) {
      throw new HarbormasterBuildFailureException();
    }

    $response = phutil_json_decode($body);

    $uri_key = 'web_url';
    $build_uri = idx($response, $uri_key);
    if (!$build_uri) {
      throw new Exception(
        pht(
          'Buildkite did not return a "%s"!',
          $uri_key));
    }

    $target_phid = $build_target->getPHID();

    $api_method = 'harbormaster.createartifact';
    $api_params = array(
      'buildTargetPHID' => $target_phid,
      'artifactType' => HarbormasterURIArtifact::ARTIFACTCONST,
      'artifactKey' => 'buildkite.uri',
      'artifactData' => array(
        'uri' => $build_uri,
        'name' => pht('View in Buildkite'),
        'ui.external' => true,
      ),
    );

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Inspect the logged HTTP response on the failed target to see exactly what Buildkite returned
  2. Retry the build once: transient API anomalies usually do not repeat
  3. If Buildkite permanently changed the field, update Phabricator/the step so $uri_key matches the new response shape
Defensive patterns

Strategy: retry

Try / catch

try {
  // execute the Buildkite step
} catch (HarbormasterBuildFailureException $ex) {
  // expected failure path (e.g. HTTP error status): mark target failed, no retry
} catch (Exception $ex) {
  // unexpected payload (e.g. missing web_url): log and retry the build once
}

Prevention

When it happens

Trigger: 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.

Common situations: Buildkite API changes after a long-lived integration; exotic proxy setups that alter response bodies. Rare in practice.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/a3c92b356a1e686a. Report an issue: GitHub.