phacility/phabricator · error · Exception

Object ("%s") does not implement interface "%s", so this typ

Error message

Object ("%s") does not implement interface "%s", so this type of object can not be unlocked.

What it means

PhabricatorUnlockEngine::newUnlockEngineForObject() requires the object to implement PhabricatorApplicationTransactionInterface, because unlocking is implemented by applying application transactions (view/edit policy changes). Objects that do not participate in the application-transactions framework cannot be unlocked, and this Exception rejects them before any engine is selected.

Source

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

<?php

abstract class PhabricatorUnlockEngine
  extends Phobject {

  final public static function newUnlockEngineForObject($object) {
    if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
      throw new Exception(
        pht(
          'Object ("%s") does not implement interface "%s", so this type '.
          'of object can not be unlocked.',
          phutil_describe_type($object),
          'PhabricatorApplicationTransactionInterface'));
    }

    if ($object instanceof PhabricatorUnlockableInterface) {
      $engine = $object->newUnlockEngine();
    } else {
      $engine = new PhabricatorDefaultUnlockEngine();
    }

    return $engine;
  }

  public function newUnlockViewTransactions($object, $user) {
    $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Check instanceof PhabricatorApplicationTransactionInterface before invoking the unlock engine and skip unsupported types with a clear message
  2. Use the object type's own administrative recovery workflow instead of the generic unlock engine
  3. If it is your custom application, implement PhabricatorApplicationTransactionInterface and an application editor on the DAO so unlocks become transaction-based

Example fix

// before
$engine = PhabricatorUnlockEngine::newUnlockEngineForObject($object);

// after: guard the interface requirement first
if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
  throw new Exception(pht('This object type can not be unlocked.'));
}
$engine = PhabricatorUnlockEngine::newUnlockEngineForObject($object);
Defensive patterns

Strategy: type-guard

Type guard

function canUnlockObject($object) {
  return ($object instanceof PhabricatorApplicationTransactionInterface);
}

Try / catch

Catch Exception around newUnlockEngineForObject() only to convert it into a friendly 'this object type cannot be unlocked' message; treat it as a permanent, non-retryable condition.

Prevention

When it happens

Trigger: Calling PhabricatorUnlockEngine::newUnlockEngineForObject($object) directly or via the unlock workflow with an object that is not a PhabricatorApplicationTransactionInterface implementer: a raw DAO row, an exotic object type, or a custom application whose storage never adopted transactions.

Common situations: Administrators attempting to unlock an unusual object type through generic tooling; custom applications missing the transaction interface; generic admin scripts passing a loaded object of the wrong class.

Related errors


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