phacility/phabricator · error · PhabricatorWorkerPermanentFailureException

Unable to find any Asana user with valid credentials to pull

Error message

Unable to find any Asana user with valid credentials to pull an OAuth token out of.

What it means

To post to Asana the worker needs an OAuth token; it tries the story author first, then every user with a linked Asana account (findAnyValidAsanaAccessToken()). If none of them yield a usable token, PhabricatorWorkerPermanentFailureException is thrown and the story task is permanently dropped. Unlike error 529, linkage exists here — the tokens themselves are missing, expired, or revoked.

Source

Thrown at src/applications/doorkeeper/worker/DoorkeeperAsanaFeedWorker.php:88

    $owner_asana_id = idx($phid_aid_map, $owner_phid);
    $all_asana_ids = array_select_keys($phid_aid_map, $all_phids);
    $all_asana_ids = array_values($all_asana_ids);

    // Even if the actor isn't a reviewer, etc., try to use their account so
    // we can post in the correct voice. If we miss, we'll try all the other
    // related users.

    $try_users = array_merge(
      array($data->getAuthorPHID()),
      array_keys($phid_aid_map));
    $try_users = array_filter($try_users);

    $access_info = $this->findAnyValidAsanaAccessToken($try_users);
    list($possessed_user, $possessed_asana_id, $oauth_token) = $access_info;

    if (!$oauth_token) {
      throw new PhabricatorWorkerPermanentFailureException(
        pht(
          'Unable to find any Asana user with valid credentials to '.
          'pull an OAuth token out of.'));
    }

    $etype_main = PhabricatorObjectHasAsanaTaskEdgeType::EDGECONST;
    $etype_sub = PhabricatorObjectHasAsanaSubtaskEdgeType::EDGECONST;

    $equery = id(new PhabricatorEdgeQuery())
      ->withSourcePHIDs(array($src_phid))
      ->withEdgeTypes(
        array(
          $etype_main,
          $etype_sub,
        ))
      ->needEdgeData(true);

    $edges = $equery->execute();

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Verify asana.application-id and application-private-key config match the Asana developer app
  2. Have the affected users unlink and re-link Asana under Settings -> External Accounts to mint fresh tokens
  3. Check daemons log (`bin/phd log`) for the underlying token-refresh errors
  4. After re-linking, generate a new story on the object to re-queue publishing
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-flight: confirm a usable Asana OAuth token exists before queueing the story.
list($user, $id, $token) = $this->findAnyValidAsanaAccessToken($try_users);
if (!$token) {
  // Queue a re-link notification instead of a publish task that will permanent-fail.
  return;
}

Prevention

When it happens

Trigger: All related users have Asana accounts linked, but every stored OAuth token fails validation (expired refresh tokens, revoked grants, app secret changed, or tokens never obtained because the provider credentials are wrong).

Common situations: Asana OAuth application secret rotated or misconfigured (asana.application-id / application-private-key), so refresh fails; users who linked long ago and revoked access; password/secret typos in the Phabricator Asana provider config causing silent token-refresh failure.

Related errors


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