CoplayDev/unity-mcp · error · ArgumentException
zipPath required
Error message
zipPath required
What it means
SafeZipExtractor.ExtractTo requires a non-empty zipPath and destDir; an empty zipPath throws ArgumentException with paramName zipPath. This is an entry-point argument guard before opening any file stream.
Source
Thrown at MCPForUnity/Editor/Services/AssetGen/Import/SafeZipExtractor.cs:23
namespace MCPForUnity.Editor.Services.AssetGen.Import
{
/// <summary>
/// Extracts a .zip into a destination directory while rejecting Zip-Slip path traversal:
/// every entry's resolved target must stay inside <c>destDir</c>. Directory entries are
/// created; file entries are written by copying the entry stream (no reliance on the
/// ZipFileExtensions helper). Used to unpack marketplace model archives (e.g. Sketchfab).
///
/// When <paramref name="allowedExtensions"/> is supplied, file entries whose extension is not
/// on the allowlist are SKIPPED (not written). Callers that extract UNTRUSTED archives into the
/// Assets tree MUST pass an allowlist of inert asset types so executable content (.cs/.dll/
/// .asmdef) can never land under Assets/ and be compiled/loaded by the Editor.
/// </summary>
public static class SafeZipExtractor
{
public static void ExtractTo(string zipPath, string destDir, ISet<string> allowedExtensions = null)
{
if (string.IsNullOrEmpty(zipPath)) throw new ArgumentException("zipPath required", nameof(zipPath));
if (string.IsNullOrEmpty(destDir)) throw new ArgumentException("destDir required", nameof(destDir));
Directory.CreateDirectory(destDir);
string destFull = Path.GetFullPath(destDir);
string prefix = destFull.EndsWith(Path.DirectorySeparatorChar.ToString())
? destFull
: destFull + Path.DirectorySeparatorChar;
using (FileStream fs = File.OpenRead(zipPath))
using (var archive = new ZipArchive(fs, ZipArchiveMode.Read))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
string name = entry.FullName;
if (string.IsNullOrEmpty(name)) continue;
// Reject traversal / absolute paths up front.
if (name.Contains("..") || Path.IsPathRooted(name))View on GitHub (pinned to c21bf496bc)
Solutions
- Ensure the zip download completed and produced a real file path before extracting.
- Guard for null/empty zipPath at the call site and surface the upstream failure.
Example fix
// before
SafeZipExtractor.ExtractTo(downloadedPath, destDir); // downloadedPath may be ""
// after
if (string.IsNullOrEmpty(downloadedPath) || !File.Exists(downloadedPath))
throw new InvalidOperationException("Download produced no archive to extract.");
SafeZipExtractor.ExtractTo(downloadedPath, destDir); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrWhiteSpace(zipPath) || !File.Exists(zipPath))
throw new InvalidOperationException("No archive file found to extract; check the download step.");
SafeZipExtractor.ExtractTo(zipPath, destDir, allowedExtensions); Type guard
static bool IsValidArchivePath(string p) => !string.IsNullOrWhiteSpace(p) && File.Exists(p);
Try / catch
try { SafeZipExtractor.ExtractTo(zipPath, destDir, allowed); }
catch (ArgumentException ex) when (ex.Message.Contains("zipPath required"))
{
// The download produced no archive; re-run download before retrying extraction.
throw new InvalidOperationException("Download step produced no archive.", ex);
} Prevention
- Confirm the download completed and the archive file exists before extracting.
- Guard for null/empty/missing path at the call site.
- Surface upstream download failures clearly instead of forwarding an empty path.
When it happens
Trigger: Calling ExtractTo with a null or empty zipPath; a download step that produced no file and forwarded an empty path.
Common situations: An upstream marketplace download failed silently leaving no local archive; path resolution returned empty due to a missing config; a caller forgetting to pass the downloaded archive path.
Related errors
- uid required
- Port must be positive.
- provider returned a disallowed file type '.{ext}'
- Unsafe zip entry rejected: {name}
- Unsafe zip entry escapes destination: {name}
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/fef6d63de2a74a58.
Report an issue: GitHub.