composer/composer · error · UnexpectedValueException

Invalid ignore rule for

Error message

Invalid ignore rule for "%s": expected an object, got %s.

What it means

Thrown by IgnorePackageRule::parseIgnoreMap() when a package key maps to a list of rule objects but one of the list elements is not an array. Each element of a list-valued ignore entry must itself be a rule-object array (with keys like constraint/reason/on-block); a non-array element (string, int, null) is rejected because it cannot be parsed into an IgnorePackageRule.

Solutions

  1. Ensure every element of a list-valued ignore entry is a rule-object array, e.g. {"vendor/pkg": [{"constraint": "^1.0"}, {"constraint": "^3.0", "on-block": false}]}.
  2. If you only need a single rule with no version constraint, use the string-reason or null form instead of a list: {"vendor/pkg": "reason"} or {"vendor/pkg": null}.
  3. Validate the list before parsing: each element of a list-valued entry must be an array.
  4. Check YAML/JSON indentation to ensure list items are objects, not scalars.

Example fix

// before
{"ignore": {"vendor/pkg": [{"constraint": "^1.0"}, "legacy"]}}
// second list element is a string -> throws

// after
{"ignore": {"vendor/pkg": [{"constraint": "^1.0"}, {"constraint": "^2.0", "reason": "legacy"}]}}
Defensive patterns

Strategy: validation

Validate before calling

// Validate list-valued ignore entries before parsing.
foreach ($config as $key => $value) {
    if (is_array($value) && !is_int($key) && isset($value[0])) {
        foreach ($value as $i => $ruleConfig) {
            if (!is_array($ruleConfig)) {
                throw new \UnexpectedValueException("ignore[$key][$i] must be a rule object");
            }
        }
    }
}
$rules = \Composer\Policy\IgnorePackageRule::parseIgnoreMap($config);

Type guard

/** @param mixed $ruleConfig */
function isRuleObject($ruleConfig): bool {
    return is_array($ruleConfig);
}

Try / catch

try {
    $rules = IgnorePackageRule::parseIgnoreMap($config);
} catch (\UnexpectedValueException $e) {
    // a list element wasn't an object - convert to {"constraint":...} shape
}

Prevention

When it happens

Trigger: parseIgnoreMap() reaches the list-of-rules branch (line 107: is_array($value) && isset($value[0])) and iterates $value; if any $ruleConfig is not an array, line 109-115 throws with the key and get_debug_type() of the offending element. E.g. {"vendor/pkg": [{"constraint": "^1.0"}, "reason"]} - second element is a string.

Common situations: Mixing a rule-object list with stray scalar entries; a YAML list where an item collapsed to a scalar; copy-paste merging a string reason into a list of objects; an inconsistent config where some entries are objects and one is a bare string.

Related errors


AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07). Data as JSON: /api/errors/0d6e5c1743f794f8. Report an issue: GitHub.

Appendix: 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 c435d285c9)