{"record":{"id":"5a5759de49530c60","repo":"Leantime/leantime","slug":"notification-plugin-zip-exists","errorCode":null,"errorMessage":"notification.plugin_zip_exists","messagePattern":"notification\\.plugin_zip_exists","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"app/Domain/Plugins/Services/Plugins.php","lineNumber":735,"sourceCode":"        ) {\n            throw new \\Exception(__('notification.plugin_cant_download'));\n        }\n\n        if (\n            is_dir($pluginDir = \"{$this->pluginDirectory}{$foldername}\")\n            && ! File::deleteDirectory($pluginDir)\n        ) {\n            throw new \\Exception(__('notification.plugin_cant_remove'));\n        }\n\n        if (! mkdir($pluginDir) && ! is_dir($pluginDir)) {\n            throw new \\RuntimeException(sprintf('Directory \"%s\" was not created', $pluginDir));\n        }\n\n        $zip = new \\ZipArchive;\n\n        match ($zip->open($temporaryFile)) {\n            \\ZipArchive::ER_EXISTS => throw new \\Exception(__('notification.plugin_zip_exists')),\n            \\ZipArchive::ER_INCONS => throw new \\Exception(__('notification.plugin_zip_inconsistent')),\n            \\ZipArchive::ER_INVAL => throw new \\Exception(__('notification.plugin_zip_invalid_arg')),\n            \\ZipArchive::ER_MEMORY => throw new \\Exception(__('notification.plugin_zip_malloc')),\n            \\ZipArchive::ER_NOENT => throw new \\Exception(__('notification.plugin_zip_no_file')),\n            \\ZipArchive::ER_NOZIP => throw new \\Exception(__('notification.plugin_zip_not_zip')),\n            \\ZipArchive::ER_OPEN => throw new \\Exception(__('notification.plugin_zip_cant_open')),\n            \\ZipArchive::ER_READ => throw new \\Exception(__('notification.plugin_zip_read_err')),\n            \\ZipArchive::ER_SEEK => throw new \\Exception(__('notification.plugin_zip_seek_err')),\n            default => throw new \\Exception(__('notification.plugin_zip_unknown_err')),\n            true => null,\n        };\n\n        if (! $zip->extractTo($pluginDir)) {\n            throw new \\Exception(__('notification.plugin_zip_cant_extract'));\n        }\n\n        $zip->close();\n","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/Leantime/leantime/blob/9a9f49f1008f4782b30f6723c54228f4f992e636/app/Domain/Plugins/Services/Plugins.php#L717-L753","documentation":"The match over ZipArchive::open($temporaryFile) maps the ER_EXISTS return code to the translated 'Zip: File already exists'. ER_EXISTS means libzip was asked to create a file that already exists, which only applies when opening with the EXCL flag - the call here passes no flags, so in practice this branch is nearly unreachable with stock libzip. If it does fire, a stale temp file with the same name is interfering.","triggerScenarios":"ZipArchive::open() on /tmp/{Folder}.zip returning ER_EXISTS: a leftover zip from a previous failed install combined with flag semantics (custom builds/older libzip), or a patched call passing ZipArchive::EXCL.","commonSituations":"Leftover /tmp/{Folder}.zip from an earlier interrupted install; environments where the temp file persists across attempts; forks that add EXCL to avoid overwriting.","solutions":["Delete the stale archive: rm /tmp/{Folder}.zip (or clear the temp dir), then retry the install.","Confirm the exact path by logging $temporaryFile; the name is derived from Content-Disposition and may differ from the plugin identifier.","Verify the open() call passes no flags; if custom code added EXCL, remove it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// clear a stale temp archive before installing\n$tmpZip = sys_get_temp_dir().'/'.Str::studly($plugin->identifier).'.zip';\nif (file_exists($tmpZip) && ! @unlink($tmpZip)) {\n    throw new RuntimeException(\"Cannot clear stale temp archive {$tmpZip}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clear /tmp/{Folder}.zip between install attempts.","Do not add ZipArchive::EXCL to the open() call without handling the exists case deliberately."],"tags":["plugins","ziparchive","marketplace"],"backgroundTag":"ziparchive-open-error","analyzedSha":"9a9f49f1008f4782b30f6723c54228f4f992e636","analyzedAt":"2026-08-21T02:37:38.966Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}