phacility/phabricator · error · Exception
Build target ("%s") has the wrong type of build step. Only C
Error message
Build target ("%s") has the wrong type of build step. Only CircleCI build steps may be updated via the CircleCI webhook. What it means
CircleCI's counterpart of the Buildkite step-type check: updateTarget() loads the target's build step and requires the implementation to be HarbormasterCircleCIBuildStepImplementation. A CircleCI webhook payload that resolves to a target owned by any other step type (Buildkite, HTTP, script, ...) is rejected before its 'status' is mapped to pass/fail messages.
Source
Thrown at src/applications/harbormaster/controller/HarbormasterCircleCIHookController.php:57
if ($target) {
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$this->updateTarget($target, $payload);
}
}
$response = new AphrontWebpageResponse();
$response->setContent(pht("Request OK\n"));
return $response;
}
private function updateTarget(
HarbormasterBuildTarget $target,
array $payload) {
$step = $target->getBuildStep();
$impl = $step->getStepImplementation();
if (!($impl instanceof HarbormasterCircleCIBuildStepImplementation)) {
throw new Exception(
pht(
'Build target ("%s") has the wrong type of build step. Only '.
'CircleCI build steps may be updated via the CircleCI webhook.',
$target->getPHID()));
}
switch (idx($payload, 'status')) {
case 'success':
case 'fixed':
$message_type = HarbormasterMessageType::MESSAGE_PASS;
break;
default:
$message_type = HarbormasterMessageType::MESSAGE_FAIL;
break;
}
$viewer = PhabricatorUser::getOmnipotentUser();
View on GitHub (pinned to 5720a38cfe)
Solutions
- Make sure the CircleCI webhook URL points at the CircleCI hook (harbormaster/circleci/) and references a target created by a CircleCI build step.
- Open the build in the Harbormaster UI and confirm the target's step is a CircleCI step; if the plan changed, trigger a new build.
- Re-send the notification only for targets that belong to CircleCI steps.
Defensive patterns
Strategy: validation
Validate before calling
$impl = $target->getBuildStep()->getStepImplementation();
if (!($impl instanceof HarbormasterCircleCIBuildStepImplementation)) {
// wrong hook for this target; do not apply the payload
} Type guard
function isCircleCITarget(HarbormasterBuildTarget $target) {
return $target->getBuildStep()->getStepImplementation()
instanceof HarbormasterCircleCIBuildStepImplementation;
} Prevention
- Keep one webhook URL per CI provider and configure it only on projects whose Harbormaster plans use that provider's step.
- After changing a plan's steps, trigger fresh builds so new targets match the new step types before old notifications arrive.
- Validate step type in custom automation before pushing external build status into targets.
When it happens
Trigger: A CircleCI notification carrying a build/step reference (query parameters on the hook URL) that points at a non-CircleCI target; swapping webhooks between the CircleCI and Buildkite endpoints; a plan whose step was changed after the build started; stale notifications for targets from an older plan revision.
Common situations: Configuring the CircleCI webhook on a repository whose Harbormaster plan uses a different CI step; replaying notifications after re-editing the plan; test payloads built from another step's target.
Related errors
- Harbormaster build target "%s" is not a Buildkite build step
- Expected "%s" property to contain a dictionary.
- Harbormaster build target "%s" does not exist.
- Buildkite request to target "%s" had the wrong authenticatio
- Object ("%s") does not implement interface "%s". Only object
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/1002f916df99e8fd.
Report an issue: GitHub.