phacility/phabricator · error · Exception

Harbormaster build target "%s" is not a Buildkite build step

Error message

Harbormaster build target "%s" is not a Buildkite build step. Only Buildkite steps may be updated via the Buildkite hook.

What it means

The target PHID from the Buildkite webhook resolved to a real HarbormasterBuildTarget, but its build step's implementation is not HarbormasterBuildkiteBuildStepImplementation. The hook refuses to mutate targets that were not created by a Buildkite step, since only those steps own the webhook contract (token settings, state mapping) the controller applies.

Source

Thrown at src/applications/harbormaster/controller/HarbormasterBuildkiteHookController.php:59

    }

    $viewer = PhabricatorUser::getOmnipotentUser();
    $target = id(new HarbormasterBuildTargetQuery())
      ->setViewer($viewer)
      ->withPHIDs(array($target_phid))
      ->needBuildSteps(true)
      ->executeOne();
    if (!$target) {
      throw new Exception(
        pht(
          'Harbormaster build target "%s" does not exist.',
          $target_phid));
    }

    $step = $target->getBuildStep();
    $impl = $step->getStepImplementation();
    if (!($impl instanceof HarbormasterBuildkiteBuildStepImplementation)) {
      throw new Exception(
        pht(
          'Harbormaster build target "%s" is not a Buildkite build step. '.
          'Only Buildkite steps may be updated via the Buildkite hook.',
          $target_phid));
    }

    $webhook_token = $impl->getSetting('webhook.token');
    $request_token = $request->getHTTPHeader('X-Buildkite-Token');

    if (!phutil_hashes_are_identical($webhook_token, $request_token)) {
      throw new Exception(
        pht(
          'Buildkite request to target "%s" had the wrong authentication '.
          'token. The Buildkite pipeline and Harbormaster build step must '.
          'be configured with the same token.',
          $target_phid));
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Confirm the build target PHID actually belongs to a Buildkite step (check the build plan in the UI: the step must be a 'Buildkite' step).
  2. Make sure the Buildkite pipeline's meta-data carries the PHID of the Buildkite step's target, not another step's target in the same build.
  3. Trigger a fresh build so each step's own webhook contract is used.
Defensive patterns

Strategy: validation

Validate before calling

$impl = $target->getBuildStep()->getStepImplementation();
if (!($impl instanceof HarbormasterBuildkiteBuildStepImplementation)) {
  // this delivery belongs to a different hook; route accordingly
}

Type guard

function isBuildkiteTarget(HarbormasterBuildTarget $target) {
  return $target->getBuildStep()->getStepImplementation()
    instanceof HarbormasterBuildkiteBuildStepImplementation;
}

Prevention

When it happens

Trigger: A buildTargetPHID belonging to a CircleCI, HTTP request, script, or other step type reaching the Buildkite hook; a plan that was edited so the step changed implementation while an old Buildkite delivery arrived; the same PHID mistakenly reused in a test payload.

Common situations: Mixing up webhook URLs between the CircleCI hook and the Buildkite hook; replaying an old webhook after the plan's step was replaced; pipelines configured with a PHID from a different step in the same plan.

Related errors


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