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

  1. Make sure the CircleCI webhook URL points at the CircleCI hook (harbormaster/circleci/) and references a target created by a CircleCI build step.
  2. 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.
  3. 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

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


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