phacility/phabricator · error · Exception

Object edit policy can not be unlocked because this object d

Error message

Object edit policy can not be unlocked because this object does not have a mutable edit policy.

What it means

newUnlockEditTransactions() mirrors the view-policy variant: it checks that the object's editor supports PhabricatorTransactions::TYPE_EDIT_POLICY before building the unlock transaction. If the edit policy is not a mutable transaction type for the object, the unlock is refused rather than attempting an inapplicable transaction.

Source

Thrown at src/applications/system/engine/PhabricatorUnlockEngine.php:46

    if (!$this->canApplyTransactionType($object, $type_view)) {
      throw new Exception(
        pht(
          'Object view policy can not be unlocked because this object '.
          'does not have a mutable view policy.'));
    }

    return array(
      $this->newTransaction($object)
        ->setTransactionType($type_view)
        ->setNewValue($user->getPHID()),
    );
  }

  public function newUnlockEditTransactions($object, $user) {
    $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;

    if (!$this->canApplyTransactionType($object, $type_edit)) {
      throw new Exception(
        pht(
          'Object edit policy can not be unlocked because this object '.
          'does not have a mutable edit policy.'));
    }

    return array(
      $this->newTransaction($object)
        ->setTransactionType($type_edit)
        ->setNewValue($user->getPHID()),
    );
  }

  public function newUnlockOwnerTransactions($object, $user) {
    throw new Exception(
      pht(
        'Object owner can not be unlocked: the unlocking engine ("%s") for '.
        'this object does not implement an owner unlocking mechanism.',
        get_class($this)));

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Try the view-policy or owner unlock variants instead; one of them is usually supported for the type
  2. If this is your application's editor, add TYPE_EDIT_POLICY to the supported transaction types for the object
  3. Use the object type's dedicated administrative recovery workflow if one exists

Example fix

// before
$xactions = $engine->newUnlockEditTransactions($object, $user);

// after: only request edit-policy unlock when the editor supports it
$types = array_fuse(
  $object->getApplicationTransactionEditor()
    ->getTransactionTypesForObject($object));
if (!isset($types[PhabricatorTransactions::TYPE_EDIT_POLICY])) {
  return pht('Edit policy can not be unlocked for this object.');
}
$xactions = $engine->newUnlockEditTransactions($object, $user);
Defensive patterns

Strategy: type-guard

Validate before calling

$types = array_fuse(
  $object->getApplicationTransactionEditor()
    ->getTransactionTypesForObject($object));
if (isset($types[PhabricatorTransactions::TYPE_EDIT_POLICY])) {
  $xactions = $engine->newUnlockEditTransactions($object, $user);
} else {
  // offer view-policy or owner unlock instead
}

Type guard

function hasMutableEditPolicy($object) {
  $types = array_fuse(
    $object->getApplicationTransactionEditor()
      ->getTransactionTypesForObject($object));
  return isset($types[PhabricatorTransactions::TYPE_EDIT_POLICY]);
}

Prevention

When it happens

Trigger: Requesting an edit-policy unlock on an object whose editor does not return TYPE_EDIT_POLICY from getTransactionTypesForObject(): object types with fixed edit policies or custom editors missing the policy types.

Common situations: Unlocking objects (for ownership recovery) whose type locks the edit policy; custom applications whose editor never declared edit-policy transaction support.

Related errors


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