phacility/phabricator · warning · Exception
Value "%s" is not valid for setting "%s": valid values are %
Error message
Value "%s" is not valid for setting "%s": valid values are %s.
What it means
Base class for settings rendered as flat <select> dropdowns. validateTransactionValue() first casts the value with phutil_string_cast() (so scalars become strings), allows empty (unset), then throws for any value not a key of getSelectOptions(). It guards the persisted enum against stale or forged keys, same contract as the option-group variant.
Source
Thrown at src/applications/settings/setting/PhabricatorSelectSetting.php:58
throw new Exception(
pht(
'Empty string is not a valid setting for "%s".',
$this->getSettingName()));
}
$this->validateTransactionValue($value);
}
final public function validateTransactionValue($value) {
$value = phutil_string_cast($value);
if (!strlen($value)) {
return;
}
$options = $this->getSelectOptions();
if (!isset($options[$value])) {
throw new Exception(
pht(
'Value "%s" is not valid for setting "%s": valid values are %s.',
$value,
$this->getSettingName(),
implode(', ', array_keys($options))));
}
return;
}
public function getTransactionNewValue($value) {
$value = phutil_string_cast($value);
if (!strlen($value)) {
return null;
}
return $value;View on GitHub (pinned to 5720a38cfe)
Solutions
- Submit a key exactly as listed in the current dropdown/options map
- After upgrading, re-open the settings form so the client posts current keys
- For custom settings, keep old keys as hidden/legacy options or migrate stored values when renaming
Defensive patterns
Strategy: type-guard
Type guard
function isValidSelectSettingValue(PhabricatorSelectSetting $setting, $value) {
$value = phutil_string_cast($value);
if (!strlen($value)) { return true; } // empty = unset, allowed
return isset($setting->getSelectOptions()[$value]);
} Try / catch
try {
// write the setting
} catch (Exception $ex) {
// invalid enum key: re-read the current options and resubmit
} Prevention
- Always read option keys from the setting's option list at runtime
- Avoid storing option keys long-term in API clients; refetch per session
- After upgrades, exercise settings forms before automation touches them
When it happens
Trigger: A settings transaction whose value (after string cast) is not one of the declared option keys - removed options after an upgrade, arbitrary strings from crafted requests, or numeric values that cast to a string with no matching key.
Common situations: Version skew between a saved client form and current options; Conduit/API callers storing literal option keys; custom settings subclasses whose option list changed without migrating stored values.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Value "%s" is not valid for setting "%s": valid values are %
- Unknown repository operation target type "%s" (in target "%s
- Unknown condition "%s"!
- Timezone "%s" is not a valid timezone identifier.
- Service "%s" is unrecognized, restricted, or you do not have
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/ece6a0b0e4705b58.
Report an issue: GitHub.