{"record":{"id":"6ffa2faf23209a22","repo":"phacility/phabricator","slug":"object-view-policy-can-not-be-unlocked-because-thi","errorCode":null,"errorMessage":"Object view policy can not be unlocked because this object does not have a mutable view policy.","messagePattern":"Object view policy can not be unlocked because this object does not have a mutable view policy\\.","errorType":"console","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/system/engine/PhabricatorUnlockEngine.php","lineNumber":29,"sourceCode":"          'of object can not be unlocked.',\n          phutil_describe_type($object),\n          'PhabricatorApplicationTransactionInterface'));\n    }\n\n    if ($object instanceof PhabricatorUnlockableInterface) {\n      $engine = $object->newUnlockEngine();\n    } else {\n      $engine = new PhabricatorDefaultUnlockEngine();\n    }\n\n    return $engine;\n  }\n\n  public function newUnlockViewTransactions($object, $user) {\n    $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;\n\n    if (!$this->canApplyTransactionType($object, $type_view)) {\n      throw new Exception(\n        pht(\n          'Object view policy can not be unlocked because this object '.\n          'does not have a mutable view policy.'));\n    }\n\n    return array(\n      $this->newTransaction($object)\n        ->setTransactionType($type_view)\n        ->setNewValue($user->getPHID()),\n    );\n  }\n\n  public function newUnlockEditTransactions($object, $user) {\n    $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;\n\n    if (!$this->canApplyTransactionType($object, $type_edit)) {\n      throw new Exception(\n        pht(","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/system/engine/PhabricatorUnlockEngine.php#L11-L47","documentation":"newUnlockViewTransactions() builds a view-policy transaction that hands the object to the unlocking user, but first asks the object's application editor which transaction types it can apply (canApplyTransactionType()). If TYPE_VIEW_POLICY is not supported for the object, its view policy is immutable through transactions and the unlock is refused.","triggerScenarios":"Requesting a view-policy unlock on an object whose editor does not return PhabricatorTransactions::TYPE_VIEW_POLICY from getTransactionTypesForObject(): types with fixed or hereditary view policies, or custom editors that never declared policy transaction types.","commonSituations":"Recovery attempts on policy-locked records whose type does not support view-policy edits; custom applications that forgot to include policy transaction types in their editor.","solutions":["Try the edit-policy or owner unlock variants instead; one of them is usually supported for the type","If this is your application's editor, add TYPE_VIEW_POLICY to the transaction types it supports for the object","Use the object type's dedicated administrative recovery workflow if one exists"],"exampleFix":"// before\n$xactions = $engine->newUnlockViewTransactions($object, $user);\n\n// after: only request view-policy unlock when the editor supports it\n$types = array_fuse(\n  $object->getApplicationTransactionEditor()\n    ->getTransactionTypesForObject($object));\nif (!isset($types[PhabricatorTransactions::TYPE_VIEW_POLICY])) {\n  return pht('View policy can not be unlocked for this object.');\n}\n$xactions = $engine->newUnlockViewTransactions($object, $user);","handlingStrategy":"type-guard","validationCode":"$types = array_fuse(\n  $object->getApplicationTransactionEditor()\n    ->getTransactionTypesForObject($object));\nif (isset($types[PhabricatorTransactions::TYPE_VIEW_POLICY])) {\n  $xactions = $engine->newUnlockViewTransactions($object, $user);\n} else {\n  // offer edit-policy or owner unlock instead\n}","typeGuard":"function hasMutableViewPolicy($object) {\n  $types = array_fuse(\n    $object->getApplicationTransactionEditor()\n      ->getTransactionTypesForObject($object));\n  return isset($types[PhabricatorTransactions::TYPE_VIEW_POLICY]);\n}","tryCatchPattern":null,"preventionTips":["Offer unlock modes dynamically from getTransactionTypesForObject(), not a fixed list","Ensure custom editors declare the policy transaction types they support"],"tags":["unlock","view-policy","policies","transactions"],"backgroundTag":"unsupported-operation-for-object-type","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}