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
- 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).
- 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.
- 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
- Give each CI provider its own webhook URL and never reuse a target PHID between steps.
- When editing plans that mid-flight builds use, expect late webhooks for replaced steps and drop them gracefully.
- Assert step type before applying external state in any custom webhook glue.
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
- Expected "%s" property to contain a dictionary.
- Harbormaster build target "%s" does not exist.
- Buildkite request to target "%s" had the wrong authenticatio
- Build target ("%s") has the wrong type of build step. Only C
- This object does not support builds with Buildkite.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/95b923ca1539c67f.
Report an issue: GitHub.