composer/composer · error · InvalidArgumentException
The json file must be an object ({})
Error message
The json file must be an object ({}) What it means
Thrown by the JsonManipulator constructor when the provided JSON contents, after trimming, do not begin with '{' and end with '}'. JsonManipulator performs surgical regex edits on a JSON *object*; a JSON array, scalar, or malformed content cannot be manipulated, so it rejects non-object input.
Source
Thrown at src/Composer/Json/JsonManipulator.php:48
(?<object> \{ (?: (?&pair) (?: , (?&pair) )*+ )?+ \s*+ \} )
(?<json> \s*+ (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
)';
/** @var string */
private $contents;
/** @var string */
private $newline;
/** @var string */
private $indent;
public function __construct(string $contents)
{
$contents = trim($contents);
if ($contents === '') {
$contents = '{}';
}
if (!Preg::isMatch('#^\{(.*)\}$#s', $contents)) {
throw new \InvalidArgumentException('The json file must be an object ({})');
}
$this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
$this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
$this->detectIndenting();
}
public function getContents(): string
{
return $this->contents . $this->newline;
}
public function addLink(string $type, string $package, string $constraint, bool $sortPackages = false): bool
{
$decoded = JsonFile::parseJson($this->contents);
// no link of that type yet
if (!isset($decoded[$type])) {
return $this->addMainKey($type, [$package => $constraint]);View on GitHub (pinned to 6ffc117740)
Solutions
- Ensure the contents passed to JsonManipulator are a full JSON object (`{ ... }`), typically the entire composer.json.
- If you have a JSON array, wrap it in an object before manipulating, or edit it with json_decode/json_encode instead.
- Re-fetch the file contents and confirm it is the root composer.json, not a sub-document.
- Validate with `json_decode($contents)` returning an object before constructing the manipulator.
Example fix
// before
$contents = file_get_contents('packages.json'); // an array [...]
$m = new JsonManipulator($contents); // throws
// after
$contents = file_get_contents('composer.json'); // an object {...}
$m = new JsonManipulator($contents); Defensive patterns
Strategy: validation
Validate before calling
$decoded = json_decode(trim($contents));
if (!($decoded instanceof \stdClass)) {
throw new \InvalidArgumentException('Contents must be a JSON object ({...}), got '.gettype($decoded));
}
$manipulator = new \Composer\Json\JsonManipulator($contents); Type guard
function isJsonObjectContents(string $contents): bool {
$decoded = json_decode(trim($contents));
return $decoded instanceof \stdClass;
} Try / catch
try {
$m = new \Composer\Json\JsonManipulator($contents);
} catch (\InvalidArgumentException $e) {
if (str_contains($e->getMessage(), 'must be an object')) {
// load the correct object-shaped file (e.g. composer.json) and retry
}
throw $e;
} Prevention
- Always pass the entire composer.json object to JsonManipulator, never a sub-array.
- Validate the top-level structure with json_decode before constructing the manipulator.
- Write tests asserting the manipulated file is an object before edit operations.
When it happens
Trigger: Constructing `new JsonManipulator($contents)` where $contents is a JSON array (`[...]`), a scalar, empty-after-trim (handled separately as '{}'), or a fragment that is not a top-level object.
Common situations: Passing the body of a 'repositories' array directly instead of the whole composer.json; loading the wrong file (e.g. an array-shaped fixture); corrupted/partial JSON; programmatic callers that assume array input.
Related errors
- "{source}" does not match the expected JSON schema
- "{file}" does not contain valid JSON {message}
- COMPOSER_AUTH environment variable is malformed, should be a
- The input does not contain valid JSON {message}
- A repository of type "package" contains an invalid package d
AI-assisted analysis of composer/composer@6ffc117740 (2026-08-07).
Data as JSON: /api/errors/5fe2125d23f00922.
Report an issue: GitHub.