phacility/phabricator · error · Exception
Value for key "%s" should be a dictionary.
Error message
Value for key "%s" should be a dictionary.
What it means
Each value in the maniphest.statuses dict must be an array/dict. After the status constant passes, !is_array($value) throws naming the key. The subsequent PhutilTypeSpec::checkMap accepts 'name' (string) with optional 'name.full', 'name.action', 'closed' (bool), 'locked', 'special', and task/transaction type fields.
Source
Thrown at src/applications/maniphest/constants/ManiphestTaskStatus.php:274
}
/**
* @task validate
*/
public static function validateConfiguration(array $config) {
foreach ($config as $key => $value) {
if (!self::isValidStatusConstant($key)) {
throw new Exception(
pht(
'Key "%s" is not a valid status constant. Status constants '.
'must be 1-64 alphanumeric characters and cannot be exclusively '.
'digits. For example, "%s" or "%s" are reasonable choices.',
$key,
'open',
'closed'));
}
if (!is_array($value)) {
throw new Exception(
pht(
'Value for key "%s" should be a dictionary.',
$key));
}
PhutilTypeSpec::checkMap(
$value,
array(
'name' => 'string',
'name.full' => 'optional string',
'name.action' => 'optional string',
'closed' => 'optional bool',
'special' => 'optional string',
'transaction.icon' => 'optional string',
'transaction.color' => 'optional string',
'silly' => 'optional bool',
'prefixes' => 'optional list<string>',
'suffixes' => 'optional list<string>',View on GitHub (pinned to 5720a38cfe)
Solutions
- Give every status constant a full dict value: {"open": {"name": "Open"}}.
- Omit statuses you do not want rather than setting them to null.
- Validate with is_array($statuses[$key]) for all keys before bin/config set maniphest.statuses.
Example fix
// before
array('open' => 'Open')
// after
array('open' => array('name' => 'Open')) Defensive patterns
Strategy: validation
Validate before calling
foreach ($statuses as $constant => $spec) {
if (!is_array($spec)) {
throw new InvalidArgumentException("Status '$constant' value must be a dict");
}
} Type guard
function is_status_spec($v) { return is_array($v) && isset($v['name']) && is_string($v['name']); } Prevention
- Every constant maps to a dict containing at least 'name'.
- Delete unused statuses instead of nulling them.
- Lint JSON structure ( braces per entry) before bin/config set.
When it happens
Trigger: A statuses entry whose value is a scalar or null: {"open": "Open"} or {"resolved": null}. The per-entry type gate fails before field-level checks like 'locked' or 'special' run.
Common situations: Hand-editing JSON where braces around one entry got dropped, producing a bare string. Template-based config generation that leaves optional entries as null instead of omitting them. YAML merges that collapsed a mapping into a scalar.
Related errors
- Configuration is not valid. Maniphest points configuration m
- Configuration is not valid. Maniphest priority configuration
- Value for key "%s" should be a dictionary.
- Key "%s" is not a valid status constant. Status constants mu
- Task status ("%s") has unrecognized value for "locked" confi
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/4baa2d3a93eb0273.
Report an issue: GitHub.