CoplayDev/unity-mcp · error · UnauthorizedAccessException
image_path must point to a file under the project's Assets f
Error message
image_path must point to a file under the project's Assets folder.
What it means
Thrown by LocalImage.ToDataUri when the supplied image path does not resolve inside the Unity project's Assets directory (AssetGenPaths.TryGetAssetsRelativePath returns false). It is a path-confinement guard: the library only inlines images that live under Assets, which prevents reading arbitrary files on disk and blocks traversal like 'Assets/../ProjectSettings'. The same message is produced non-throwingly by ResolveExisting, so hitting the throw means ToDataUri was called without that pre-check.
Source
Thrown at MCPForUnity/Editor/Services/AssetGen/Providers/LocalImage.cs:53
string abs = AssetGenPaths.ToAbsolute(rel);
if (!File.Exists(abs)) { error = $"Source image not found: {path}"; return false; }
if (!SupportedExtensions.Contains(Path.GetExtension(abs)))
{
error = $"Unsupported image type '{Path.GetExtension(abs)}'. Use .png, .jpg, .jpeg, .webp, or .gif.";
return false;
}
absPath = abs;
return true;
}
/// <summary>
/// Read a local image and return a "data:image/<mime>;base64,..." URI. Throws
/// <see cref="NotSupportedException"/> for an unsupported extension.
/// </summary>
public static string ToDataUri(string absPath)
{
if (!AssetGenPaths.TryGetAssetsRelativePath(absPath, out string rel))
throw new UnauthorizedAccessException("image_path must point to a file under the project's Assets folder.");
absPath = AssetGenPaths.ToAbsolute(rel);
string mime = MimeFromExtension(Path.GetExtension(absPath));
byte[] bytes = File.ReadAllBytes(absPath);
return "data:" + mime + ";base64," + Convert.ToBase64String(bytes);
}
private static string MimeFromExtension(string ext)
{
switch ((ext ?? string.Empty).ToLowerInvariant())
{
case ".png": return "image/png";
case ".jpg":
case ".jpeg": return "image/jpeg";
case ".webp": return "image/webp";
case ".gif": return "image/gif";
default:
throw new NotSupportedException(
$"Unsupported image type '{ext}' for image input. Use .png, .jpg, .jpeg, .webp, or .gif.");View on GitHub (pinned to c21bf496bc)
Solutions
- Move or copy the image into the project's Assets/ folder and pass an 'Assets/...' relative path (or an absolute path under Assets).
- If the image must stay external, host it at an http(s) URL and pass image_url instead of image_path.
- Pre-validate with LocalImage.ResolveExisting before calling ToDataUri so the error surfaces as a user-facing message rather than an exception.
Example fix
// before
string dataUri = LocalImage.ToDataUri(req.ImagePath); // throws UnauthorizedAccessException
// after
if (!LocalImage.ResolveExisting(req.ImagePath, out string abs, out string err))
return ErrorResponse(err);
string dataUri = LocalImage.ToDataUri(abs); Defensive patterns
Strategy: validation
Validate before calling
// Pre-check path confinement before inlining (handler-side, same assembly):
if (!LocalImage.ResolveExisting(imagePath, out string abs, out string err))
return ErrorResponse(err);
// abs is now a verified in-Assets file; safe to call ToDataUri(abs). Type guard
// Confines an image path to the project Assets folder before use.
static bool IsPathUnderAssets(string path)
=> MCPForUnity.Editor.Helpers.AssetGenPaths.TryGetAssetsRelativePath(path, out _); Try / catch
try { string uri = LocalImage.ToDataUri(absPath); }
catch (System.UnauthorizedAccessException ex)
{ /* path escaped Assets — move file under Assets/ or use image_url */ } Prevention
- Always route local images through LocalImage.ResolveExisting before ToDataUri; it returns the same errors non-throwingly.
- Keep input images under Assets/ and pass 'Assets/...' relative paths.
- For external images, host them and pass image_url instead of image_path.
When it happens
Trigger: Calling an asset-gen flow that inlines a local image (Meshy image-to-3D at MeshyAdapter.cs:55, OpenRouter image input at OpenRouterAdapter.cs:44) with an image_path that is absolute but outside the project, relative but not starting with 'Assets/', or a Packages/ / PackageCache path.
Common situations: Passing a path to Downloads/Desktop/a sibling project; a typo; passing a Packages folder path; passing an absolute Library/ path; copied a path from another OS with backslashes that still resolves outside Assets.
Related errors
- Unsupported image type '{ext}' for image input. Use .png, .j
- {context}: refusing to send credentials to an unexpected hos
- CredWrite failed (Win32 {GetLastWin32Error})
- provider returned a disallowed file type '.{ext}'
- Unsafe zip entry rejected: {name}
AI-assisted analysis of CoplayDev/unity-mcp@c21bf496bc (2026-08-13).
Data as JSON: /api/errors/ef3bb811b48fd338.
Report an issue: GitHub.