{"record":{"id":"19fa0da4278c7bd0","repo":"phacility/phabricator","slug":"unable-to-find-any-asana-user-with-valid-credentia","errorCode":null,"errorMessage":"Unable to find any Asana user with valid credentials to pull an OAuth token out of.","messagePattern":"Unable to find any Asana user with valid credentials to pull an OAuth token out of\\.","errorType":"exception","errorClass":"PhabricatorWorkerPermanentFailureException","httpStatus":null,"severity":"error","filePath":"src/applications/doorkeeper/worker/DoorkeeperAsanaFeedWorker.php","lineNumber":88,"sourceCode":"\n    $owner_asana_id = idx($phid_aid_map, $owner_phid);\n    $all_asana_ids = array_select_keys($phid_aid_map, $all_phids);\n    $all_asana_ids = array_values($all_asana_ids);\n\n    // Even if the actor isn't a reviewer, etc., try to use their account so\n    // we can post in the correct voice. If we miss, we'll try all the other\n    // related users.\n\n    $try_users = array_merge(\n      array($data->getAuthorPHID()),\n      array_keys($phid_aid_map));\n    $try_users = array_filter($try_users);\n\n    $access_info = $this->findAnyValidAsanaAccessToken($try_users);\n    list($possessed_user, $possessed_asana_id, $oauth_token) = $access_info;\n\n    if (!$oauth_token) {\n      throw new PhabricatorWorkerPermanentFailureException(\n        pht(\n          'Unable to find any Asana user with valid credentials to '.\n          'pull an OAuth token out of.'));\n    }\n\n    $etype_main = PhabricatorObjectHasAsanaTaskEdgeType::EDGECONST;\n    $etype_sub = PhabricatorObjectHasAsanaSubtaskEdgeType::EDGECONST;\n\n    $equery = id(new PhabricatorEdgeQuery())\n      ->withSourcePHIDs(array($src_phid))\n      ->withEdgeTypes(\n        array(\n          $etype_main,\n          $etype_sub,\n        ))\n      ->needEdgeData(true);\n\n    $edges = $equery->execute();","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/doorkeeper/worker/DoorkeeperAsanaFeedWorker.php#L70-L106","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify asana.application-id and application-private-key config match the Asana developer app","Have the affected users unlink and re-link Asana under Settings -> External Accounts to mint fresh tokens","Check daemons log (`bin/phd log`) for the underlying token-refresh errors","After re-linking, generate a new story on the object to re-queue publishing"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Pre-flight: confirm a usable Asana OAuth token exists before queueing the story.\nlist($user, $id, $token) = $this->findAnyValidAsanaAccessToken($try_users);\nif (!$token) {\n  // Queue a re-link notification instead of a publish task that will permanent-fail.\n  return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep asana.application-id / application-private-key in sync with the Asana developer app","Ask users to re-link Asana after any OAuth app secret rotation","Distinguish this from error 529: accounts are linked here, tokens are the problem"],"tags":["phabricator","asana","oauth","token","doorkeeper","worker"],"backgroundTag":"oauth-token-unavailable","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}