phacility/phabricator · error · Exception
CircleCI did not return a "%s"!
Error message
CircleCI did not return a "%s"!
What it means
The POST to circleci.com/api/v1/project/... returned a non-error HTTP status and the body parsed as JSON, but the decoded object has no 'build_url' key. The step needs that URL to create the 'View in CircleCI' URI artifact, so a 2xx response without build_url (typically a JSON error object such as {"message": ...} from CircleCI) fails the build with this exception.
Source
Thrown at src/applications/harbormaster/step/HarbormasterCircleCIBuildStepImplementation.php:207
->addHeader('Accept', 'application/json')
->setTimeout(60);
$this->resolveFutures(
$build,
$build_target,
array($future));
$this->logHTTPResponse($build, $build_target, $future, pht('CircleCI'));
list($status, $body) = $future->resolve();
if ($status->isError()) {
throw new HarbormasterBuildFailureException();
}
$response = phutil_json_decode($body);
$build_uri = idx($response, 'build_url');
if (!$build_uri) {
throw new Exception(
pht(
'CircleCI did not return a "%s"!',
'build_url'));
}
$target_phid = $build_target->getPHID();
// Write an artifact to create a link to the external build in CircleCI.
$api_method = 'harbormaster.createartifact';
$api_params = array(
'buildTargetPHID' => $target_phid,
'artifactType' => HarbormasterURIArtifact::ARTIFACTCONST,
'artifactKey' => 'circleci.uri',
'artifactData' => array(
'uri' => $build_uri,
'name' => pht('View in CircleCI'),
'ui.external' => true,View on GitHub (pinned to 5720a38cfe)
Solutions
- Open the build target log: logHTTPResponse() recorded the raw HTTP response, which shows exactly what CircleCI returned.
- Confirm the project is enabled on CircleCI and the token has access to the namespace/project the step built.
- Re-test the exact URL from the log with curl using the same token to reproduce the response outside Phabricator.
- If CircleCI's API shape changed, update/patch HarbormasterCircleCIBuildStepImplementation or upgrade Phabricator.
Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check reachability before the build (optional, does not guarantee build_url):
list($status) = id(new HTTPSFuture('https://circleci.com/api/v1/me?circle-token='.$token))
->resolve();
if ($status->isError()) {
// token/project problem - fix before running builds
} Try / catch
try {
// run the CircleCI step
} catch (Exception $ex) {
if (preg_match('/did not return a "build_url"/', $ex->getMessage())) {
// inspect the logged HTTP response body for the actual CircleCI payload;
// fix project/token config, then re-run the build
}
} Prevention
- Enable ('Follow') the project on CircleCI before wiring the step.
- Verify the token has access to the exact namespace/project the step derives from the GitHub path.
- Keep Phabricator patched so CircleCI API changes are picked up; watch CircleCI deprecation notices for the v1 API.
When it happens
Trigger: CircleCI answers 200 with an error payload: project not enabled on CircleCI, token lacking scope for the project, or an API-shape change (the v1 API being deprecated/changed). Also possible with intermediaries (proxies) that return their own JSON on 2xx.
Common situations: The CircleCI project was never enabled ('Follow' the project on CircleCI); the token belongs to a different user/org; CircleCI v1 API behavior changed after maintenance; builds worked before a CircleCI or Phabricator upgrade.
Related errors
- Buildkite did not return a "%s"!
- Object ("%s") does not implement interface "%s". Only object
- Object ("%s") claims "%s" is a GitHub repository URI, but th
- Object ("%s") claims "%s" is a GitHub repository URI, but th
- Unable to load API token ("%s")!
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/552f8771058086ba.
Report an issue: GitHub.