{"record":{"id":"3d070ef7d9caa874","repo":"phacility/phabricator","slug":"s-has-no-visible-object-on-the-other-side-this-l","errorCode":null,"errorMessage":"%s has no visible object on the other side; this likely indicates the Asana task has been deleted.","messagePattern":"(.+?) has no visible object on the other side; this likely indicates the Asana task has been deleted\\.","errorType":"exception","errorClass":"PhabricatorWorkerPermanentFailureException","httpStatus":null,"severity":"error","filePath":"src/applications/doorkeeper/worker/DoorkeeperAsanaFeedWorker.php","lineNumber":248,"sourceCode":"\n    $dst_phid = $parent_ref->getExternalObject()->getPHID();\n\n    // Update the main edge.\n\n    $edge_data = array(\n      'cursor' => $story->getChronologicalKey(),\n    ) + $extra_data;\n\n    $edge_options = array(\n      'data' => $edge_data,\n    );\n\n    id(new PhabricatorEdgeEditor())\n      ->addEdge($src_phid, $etype_main, $dst_phid, $edge_options)\n      ->save();\n\n    if (!$parent_ref->getIsVisible()) {\n      throw new PhabricatorWorkerPermanentFailureException(\n        pht(\n          '%s has no visible object on the other side; this '.\n          'likely indicates the Asana task has been deleted.',\n          'DoorkeeperExternalObject'));\n    }\n\n    // Now, handle the subtasks.\n\n    $sub_editor = new PhabricatorEdgeEditor();\n\n    // First, find all the object references in Phabricator for tasks that we\n    // know about and import their objects from Asana.\n    $sub_edges = $edges[$src_phid][$etype_sub];\n    $sub_refs = array();\n    $subtask_data = $this->getAsanaSubtaskData($object);\n    $have_phids = array();\n\n    if ($sub_edges) {","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/doorkeeper/worker/DoorkeeperAsanaFeedWorker.php#L230-L266","documentation":"After saving the Phabricator-to-Asana edge for the main task, the worker re-checks the imported ref's visibility. If the parent Asana object is not visible (the Asana task was deleted, or the possessed user lost access), PhabricatorWorkerPermanentFailureException is thrown so the daemon stops trying to update a dead target. This is by-design cleanup behavior, not a bug: the edge was already recorded and the story is intentionally dropped.","triggerScenarios":"The Asana task that a Phabricator object is mirrored to has been deleted or made inaccessible to every candidate possessed user between import and edge save. The same object later produces new feed stories, each failing permanently.","commonSituations":"Someone deletes the Asana task manually while Phabricator keeps mirroring updates; the Asana task is moved to a workspace the integration cannot see; de-provisioned users whose tokens can no longer read the task.","solutions":["Treat it as expected behavior: the deleted-task story is dropped permanently and no action is needed","To stop the noise, remove the stale PhabricatorObjectHasAsanaTask edge from the object so new stories stop mirroring","If the task should still exist, verify it is visible to a user with a linked, working Asana account"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Before mirroring, check the target Asana object still exists/is visible.\nif (!$parent_ref->getIsVisible()) {\n  // Drop or clean up the edge instead of saving it and letting the worker fail.\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  $worker->executeTask();\n} catch (PhabricatorWorkerPermanentFailureException $ex) {\n  // Expected for deleted Asana tasks: acknowledge and stop retrying.\n  phlog(pht('Asana task gone, dropping story: %s', $ex->getMessage()));\n}","preventionTips":["Remove stale PhabricatorObjectHasAsanaTask edges when the Asana task is known-deleted","Treat permanent failures on deleted tasks as normal lifecycle noise in alerting","Keep a runbook mapping each doorkeeper permanent-failure message to its expected action"],"tags":["phabricator","asana","doorkeeper","deleted-object","worker"],"backgroundTag":"external-object-deleted","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}