composer/composer · error · UnexpectedValueException
Invalid ignore rule for "%s": expected an object, got %s.
Error message
Invalid ignore rule for "%s": expected an object, got %s.
What it means
Thrown by IgnorePackageRule::parseIgnoreMap() when iterating a list-of-rules value (e.g. `"vendor/pkg": [{...}, {...}]`) and one of the elements is not an array. Each element of the list must be a rule object (associative array with constraint/reason/on-block/on-audit keys); non-array elements are rejected.
Source
Thrown at src/Composer/Policy/IgnorePackageRule.php:110
}
// Simple string reason: "vendor/pkg": "reason"
if (is_string($value) && !is_int($key)) {
$rules[$key][] = new self($key, new MatchAllConstraint(), $value);
continue;
}
// Numeric key with string value: ["vendor/pkg"]
if (is_int($key) && is_string($value)) {
$rules[$value][] = new self($value, new MatchAllConstraint());
continue;
}
// Array of rule objects: "vendor/pkg": [{...}, {...}]
if (is_array($value) && !is_int($key) && isset($value[0])) {
foreach ($value as $ruleConfig) {
if (!is_array($ruleConfig)) {
throw new \UnexpectedValueException(sprintf(
'Invalid ignore rule for "%s": expected an object, got %s.',
$key,
get_debug_type($ruleConfig)
));
}
$rules[$key][] = self::fromRuleObject($key, $ruleConfig, $parser);
}
continue;
}
// Single rule object: "vendor/pkg": {"constraint": "...", ...}
if (is_array($value) && !is_int($key)) {
$rules[$key][] = self::fromRuleObject($key, $value, $parser);
continue;
}
throw new \UnexpectedValueException(sprintf(
'Invalid ignore entry at key "%s": value of type %s is not a supported shape.'View on GitHub (pinned to 6ffc117740)
Solutions
- Make every element of the list an object: `ignore: { 'vendor/pkg': [{ 'constraint': '^1.0' }, { 'constraint': '^3.0' }] }`.
- For a single reason string, use the direct form: `ignore: { 'vendor/pkg': 'reason text' }` (no list wrapper).
- For one rule with options, use a single object, not a list: `ignore: { 'vendor/pkg': { 'constraint': '^1.0', 'reason': '...' } }`.
Example fix
// before ['ignore' => ['vendor/pkg' => ['legacy reason', ['constraint' => '^1.0']]]] // after ['ignore' => ['vendor/pkg' => [['constraint' => '^1.0', 'reason' => 'legacy']]]]
Defensive patterns
Strategy: validation
Validate before calling
function ignoreListEntriesAreObjects(array $listValue): bool {
foreach ($listValue as $entry) {
if (!is_array($entry) || array_is_list($entry) && count($entry) === 0) {
// a rule object is associative; reject sequential arrays and non-arrays
if (!is_array($entry)) {
return false;
}
}
}
return true;
} Type guard
function isIgnoreRuleObject($value): bool {
return is_array($value)
&& (isset($value['constraint']) || isset($value['reason']) || isset($value['on-block']) || isset($value['on-audit']));
} Prevention
- Wrap multi-range ignore rules in objects, never bare strings, inside a list.
- Use the direct string form for single reasons instead of a list of one string.
- Validate list-of-rules shape with array_is_list detection in a config checker.
When it happens
Trigger: Config like `ignore: { 'vendor/pkg': ['reason', { 'constraint': '^1.0' }] }` where one list element is a string rather than an object. Reached at IgnorePackageRule.php:110 inside the `is_array($value) && isset($value[0])` branch when is_array($ruleConfig) is false for some element.
Common situations: Mixing the simple-string reason form with the list-of-objects form; YAML flow style merges values; user assumes positional strings are allowed in the list (they are not — strings belong as the direct value, not inside the list).
Related errors
- Invalid ignore-id entry at index %d: expected an advisory ID
- Invalid ignore-id entry for "%s": value of type %s is not a
- Invalid ignore entry at key "%s": value of type %s is not a
- Invalid ignore-severity entry at index %d: expected a severi
- Invalid ignore-severity entry for "%s": value of type %s is
AI-assisted analysis of composer/composer@6ffc117740 (2026-08-07).
Data as JSON: /api/errors/0d6e5c1743f794f8.
Report an issue: GitHub.