phacility/phabricator · error · PhutilArgumentUsageException

OAuth client "%s" is already untrusted.

Error message

OAuth client "%s" is already untrusted.

What it means

Thrown by `bin/auth untrust-oauth-client` when the target client's isTrusted flag is already 0. The workflow checks getIsTrusted() and aborts with this PhutilArgumentUsageException before setIsTrusted(0)/save(), so it never performs a redundant write. The database is left exactly as it was.

Source

Thrown at src/applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php:46

      throw new PhutilArgumentUsageException(
        pht(
          'Specify an OAuth client ID with %s.',
          '--id'));
    }

    $client = id(new PhabricatorOAuthServerClientQuery())
      ->setViewer($this->getViewer())
      ->withIDs(array($id))
      ->executeOne();

    if (!$client) {
      throw new PhutilArgumentUsageException(
        pht(
          'Failed to find an OAuth client with ID %s.', $id));
    }

    if (!$client->getIsTrusted()) {
      throw new PhutilArgumentUsageException(
        pht(
          'OAuth client "%s" is already untrusted.',
          $client->getName()));
    }

    $client->setIsTrusted(0);
    $client->save();

    $console = PhutilConsole::getConsole();
    $console->writeOut(
      "%s\n",
      pht(
        'OAuth client "%s" is now trusted.',
        $client->getName()));
  }

}

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Treat the message as confirmation of the desired state — the client is already untrusted, nothing to do.
  2. In scripts, catch PhutilArgumentUsageException containing 'already untrusted' and treat it as success (or check isTrusted in the DB first).
  3. If you expected this client to be trusted, double-check the `--id` — you may be inspecting a different client than intended.
  4. To move it back to trusted, use `bin/auth trust-oauth-client --id N`.

Example fix

// before
$ bin/auth untrust-oauth-client --id 7   # second run
OAuth client "wiki-frontend" is already untrusted.

// after — check current state instead of assuming
$ mysql ... -e "SELECT id,name,isTrusted FROM oauth_server_oauthserverclient WHERE id=7;"
Defensive patterns

Strategy: validation

Validate before calling

if (!$client->getIsTrusted()) {
  // already untrusted: skip the untrust command
} else {
  // safe to run: bin/auth untrust-oauth-client --id <id>
}

Try / catch

try {
  // run untrust-oauth-client
} catch (PhutilArgumentUsageException $ex) {
  if (strpos($ex->getMessage(), 'already untrusted') !== false) {
    // desired state already reached; exit 0
  }
}

Prevention

When it happens

Trigger: Running `bin/auth untrust-oauth-client --id N` twice in a row, or untrusting a client that was never trusted in the first place.

Common situations: Idempotent deployment scripts re-run the command on every iteration; a security incident runbook is executed after someone already untrusted the client; the admin is uncertain of the current state and probes with the command.

Related errors


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