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
- Compare the key in the exception message against the keys returned by the adapter's newDefaultOptions() and accepted by validateOptions() - they must match exactly.
- Add the missing key to newDefaultOptions() (with a sensible default) and to the PhutilTypeSpec/checkMap in validateOptions().
- Never call setOptions() with a partial array; build options as newDefaultOptions() + your overrides before handing them over.
- 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
- In custom adapters, keep one constant/source for option key names and reference it from both newDefaultOptions()/validateOptions() and getOption() calls.
- Never call setOptions() with a partial array - it replaces the entire option set.
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
- Adapter ("%s") is configured for medium "%s", but this is no
- Configuration file is not properly formatted JSON. %s
- Configuration file has improper configuration keys at top le
- Two servers (at indexes "%s" and "%s") both bind to the same
- A specified server (at index "%s", on port "%s") has an inva
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/8abecafd091b7206.
Report an issue: GitHub.