composer/composer · error · UnexpectedValueException
{dir} does not exist and could not be created.
Error message
{dir} does not exist and could not be created. What it means
Thrown by JsonFile::write() when the target directory does not exist AND @mkdir($dir, 0777, true) failed (the @ suppresses the warning; the false return triggers the exception). The recursive mkdir could not create the path — usually a permission denial or a parent that is not writable.
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 6ffc117740)
Solutions
- Ensure the parent of the target directory exists and is writable by the PHP process.
- Fix ownership/permissions: `chown -R <user> <parent>` and `chmod -R u+w <parent>`.
- Check the filesystem is mounted read-write (`mount | grep <path>`).
- Remove any file occupying a parent path component that should be a directory.
Example fix
// before $jsonFile->write($data); // vendor/composer not creatable (read-only mount) // after chmod -R u+w vendor # or fix the container mount to be read-write $jsonFile->write($data);
Defensive patterns
Strategy: validation
Validate before calling
$dir = dirname($path);
if (!is_dir($dir)) {
if (!@mkdir($dir, 0777, true)) {
if (!is_writable(dirname($dir))) {
throw new \UnexpectedValueException("Cannot create $dir: parent not writable");
}
throw new \UnexpectedValueException("Cannot create directory $dir");
}
} Type guard
function isDirCreatable(string $dir): bool {
if (is_dir($dir)) return true;
$parent = $dir;
while (!is_dir($parent = dirname($parent))) {
if (file_exists($parent)) return false;
}
return is_writable($parent);
} Try / catch
try {
$jsonFile->write($data);
} catch (\UnexpectedValueException $e) {
if (str_contains($e->getMessage(), 'could not be created')) {
// fix permissions/ownership/mount, then retry
}
throw $e;
} Prevention
- Run composer with write access to the project tree.
- Ensure the filesystem is mounted read-write.
- Pre-create vendor/ and other writable dirs in containers with correct ownership.
When it happens
Trigger: Calling write() where dirname($path) is missing and mkdir(..., true) returns false: no write permission on the parent, a read-only filesystem, or a parent path component is a file.
Common situations: vendor/ directory not writable (composer running as wrong user); read-only mount; a parent path component occupied by a file; running inside a container with a read-only bind mount; selinux denying directory creation.
Related errors
- The file "{path}" is not readable.
- Could not read {path} {exception message}
- {realpath dir} exists and is not a directory.
- Could not create archive '%s' from '%s': %s
- Composer update failed: the "{tmpDir}" directory used to dow
AI-assisted analysis of composer/composer@6ffc117740 (2026-08-07).
Data as JSON: /api/errors/39be473437918104.
Report an issue: GitHub.