phacility/phabricator · error · Exception

Mailer ("%s") is attempting to access unknown option ("%s").

Error message

Mailer ("%s") is attempting to access unknown option ("%s").

What it means

Mail adapters read their configuration only through getOption($key), which serves keys present in the $options array installed by setOptions(). Phabricator's mailer factory merges each adapter's newDefaultOptions() with config before calling setOptions(), so in practice this exception means the adapter's own code asked for a key that its option schema never declared - a misspelled key name, or a caller that re-invoked setOptions() with a partial array and wiped the defaults.

Source

Thrown at src/applications/metamta/adapter/PhabricatorMailAdapter.php:121

    return $this;
  }

  final public function getSupportsInbound() {
    return $this->supportsInbound;
  }

  final public function setSupportsOutbound($supports_outbound) {
    $this->supportsOutbound = $supports_outbound;
    return $this;
  }

  final public function getSupportsOutbound() {
    return $this->supportsOutbound;
  }

  final public function getOption($key) {
    if (!array_key_exists($key, $this->options)) {
      throw new Exception(
        pht(
          'Mailer ("%s") is attempting to access unknown option ("%s").',
          get_class($this),
          $key));
    }

    return $this->options[$key];
  }

  final public function setOptions(array $options) {
    $this->validateOptions($options);
    $this->options = $options;
    return $this;
  }

  abstract protected function validateOptions(array $options);

  abstract public function newDefaultOptions();

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Compare the key in the exception message against the keys returned by the adapter's newDefaultOptions() and accepted by validateOptions() - they must match exactly.
  2. Add the missing key to newDefaultOptions() (with a sensible default) and to the PhutilTypeSpec/checkMap in validateOptions().
  3. Never call setOptions() with a partial array; build options as newDefaultOptions() + your overrides before handing them over.
  4. If you are hitting this from config only, make sure the cluster.mailers 'options' keys use the exact names the adapter declares.

Example fix

// before: adapter reads a key it never declares
public function newDefaultOptions() {
  return array('apikey' => null);
}
public function sendMessage($message) {
  $key = $this->getOption('api-key'); // throws: unknown option
}

// after: declared key and read key match
public function newDefaultOptions() {
  return array('api-key' => null);
}
public function sendMessage($message) {
  $key = $this->getOption('api-key');
}
Defensive patterns

Strategy: validation

Validate before calling

// When building adapters manually, always merge defaults before setOptions().
$options = $adapter->newDefaultOptions() + $config_options;
$adapter->setOptions($options);
// And assert every key you will read is declared:
foreach ($keys_you_read as $key) {
  if (!array_key_exists($key, $options)) {
    throw new Exception('Adapter option "'.$key.'" is not declared.');
  }
}

Prevention

When it happens

Trigger: Writing or extending a PhabricatorMailAdapter subclass where getOption('api-key') does not match a key defined in newDefaultOptions()/validateOptions() (e.g. declared 'apikey' but read 'api-key'); calling setOptions($partial_options) directly, which validates then replaces the whole options array, dropping default keys the adapter later reads.

Common situations: Custom or third-party mail adapters written against an older option naming; upstream renames an option key while an install carries a local adapter patch; code that constructs adapters manually (tests, tooling) and forgets to merge newDefaultOptions().

Related errors


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