composer/composer · error · UnexpectedValueException
does not exist and could not be created.
Error message
${dir} does not exist and could not be created. What it means
JsonFile::write() throws an UnexpectedValueException when the parent directory does not exist and @mkdir($dir, 0777, true) returns false. mkdir fails silently here (error suppressed with @), so the message reports only that creation failed; the suppressed error usually indicates a permissions issue or a path collision.
Solutions
- Fix ownership/permissions on the parent directory so the PHP user can write and create subdirs: `chown -R <user>:<group> <parent>` and `chmod -R u+w <parent>`.
- Ensure you are running composer as the directory owner (not root) or with matching UID in Docker.
- Remove any file that conflicts with a needed directory segment.
- Check open_basedir / disable functions if on a restricted host.
Example fix
# before (docker, wrong UID) $ composer install > .../vendor does not exist and could not be created. # after $ chown -R $USER:$USER . $ chmod -R u+w . $ composer install
Defensive patterns
Strategy: validation
Validate before calling
$dir = dirname($path);
if (!is_dir($dir)) {
if (file_exists($dir)) {
throw new \RuntimeException("$dir is a file, cannot create directory");
}
if (!@mkdir($dir, 0777, true)) {
throw new \RuntimeException("Cannot create $dir: " . (error_get_last()['message'] ?? 'permission denied'));
}
} Type guard
function dirIsCreatable(string $dir): bool {
if (is_dir($dir)) return true;
if (file_exists($dir)) return false;
return is_writable(dirname($dir));
} Try / catch
try {
$jsonFile->write($data);
} catch (\UnexpectedValueException $e) {
if (str_ends_with($e->getMessage(), ' does not exist and could not be created.')) {
// fix ownership/permissions or open_basedir, then retry
throw new \RuntimeException('Cannot create dir for ' . $path . ': ' . $e->getMessage(), 0, $e);
}
throw $e;
} Prevention
- Run composer as the directory owner; in Docker, match the container UID to the mounted volume owner.
- chmod -R u+w the project root (and vendor) so composer can create needed subdirs.
- Ensure the path is inside open_basedir on restricted hosts.
When it happens
Trigger: Calling write() where dirname($path) is missing and cannot be created — e.g. a parent segment lacks write permission, a component of the path is an existing file, or open_basedir restricts the location.
Common situations: vendor/ or its parent not writable by the PHP user (common on shared hosts, Docker with wrong UID, CI running as non-owner); running composer as root with a HOME that maps to an unreadable path; open_basedir restriction; a file blocking the directory creation.
Related errors
- The file " " is not readable.
- Could not read
- Could not read
- exists and is not a directory.
- The file " " is not readable.
AI-assisted analysis of composer/composer@c435d285c9 (2026-08-07).
Data as JSON: /api/errors/6b38ce2f9a6c3173.
Report an issue: GitHub.
Appendix: source
Thrown at src/Composer/Json/JsonFile.php:154
* @return void
*/
public function write(array $hash, int $options = JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
{
if ($this->path === 'php://memory') {
file_put_contents($this->path, static::encode($hash, $options, $this->indent));
return;
}
$dir = dirname($this->path);
if (!is_dir($dir)) {
if (file_exists($dir)) {
throw new \UnexpectedValueException(
realpath($dir).' exists and is not a directory.'
);
}
if (!@mkdir($dir, 0777, true)) {
throw new \UnexpectedValueException(
$dir.' does not exist and could not be created.'
);
}
}
$retries = 3;
while ($retries--) {
try {
$this->filePutContentsIfModified($this->path, static::encode($hash, $options, $this->indent). ($options & JSON_PRETTY_PRINT ? "\n" : ''));
break;
} catch (\Exception $e) {
if ($retries > 0) {
usleep(500000);
continue;
}
throw $e;
}View on GitHub (pinned to c435d285c9)