arduino/Arduino · error · Exception

Can't download {0}: invalid filename or exinsting directory

Error message

Can't download {0}: invalid filename or exinsting directory

What it means

DownloadableContributionsDownloader.download() derives the output file name from the contribution's archive file name and refuses to proceed if the resulting path would overwrite an existing directory (or the name is otherwise invalid after path filtering). It throws a generic Exception with a formatted message naming the archive.

Source

Thrown at arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java:65

public class DownloadableContributionsDownloader {
  private final File stagingFolder;

  public DownloadableContributionsDownloader(File _stagingFolder) {
    stagingFolder = _stagingFolder;
  }

  public File download(DownloadableContribution contribution, Progress progress, final String statusText, ProgressListener progressListener, boolean allowCache) throws Exception {
    return download(contribution, progress, statusText, progressListener, false, allowCache);
  }

  public File download(DownloadableContribution contribution, Progress progress, final String statusText, ProgressListener progressListener, boolean noResume, boolean allowCache) throws Exception {
    URL url = new URL(contribution.getUrl());
    // Filter out paths from file name
    String filename = new File(contribution.getArchiveFileName()).getName();
    Path outputFile = Paths.get(stagingFolder.getAbsolutePath(), filename).normalize();
    if (outputFile.toFile().isDirectory()) {
      throw new Exception(format("Can't download {0}: invalid filename or exinsting directory", contribution.getArchiveFileName()));
    }

    // Ensure the existence of staging folder
    Files.createDirectories(stagingFolder.toPath());

    if (!hasChecksum(contribution) && Files.exists(outputFile)) {
      Files.delete(outputFile);
    }

    boolean downloaded = false;
    while (true) {
      // Need to download or resume downloading?
      if (!Files.isRegularFile(outputFile, LinkOption.NOFOLLOW_LINKS) || (Files.size(outputFile) < contribution.getSize())) {
        download(url, outputFile.toFile(), progress, statusText, progressListener, noResume, allowCache);
        downloaded = true;
      }

      // Test checksum

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Inspect the staging folder and remove the directory that collides with the archive file name, then retry the download.
  2. Check the package index URL / archive file name for the offending contribution and fix or update the index.
  3. Clear the staging directory (e.g. ~/Arduino/staging) if its contents are in an inconsistent state.
  4. Pre-validate the file name before calling download(): ensure it is a plain file name and not an existing directory path.

Example fix

// before
downloader.download(contribution, progress, "Downloading", listener, false, true);
// after
String name = new File(contribution.getArchiveFileName()).getName();
File out = new File(stagingDir, name);
if (out.isDirectory()) {
  FileUtils.deleteDirectory(out); // or fail fast with a clear message
}
downloader.download(contribution, progress, "Downloading", listener, false, true);
Defensive patterns

Strategy: validation

Validate before calling

File out = new File(stagingFolder, new File(contribution.getArchiveFileName()).getName());
if (out.isDirectory()) { throw new IllegalStateException("Staging path is a directory: " + out); }

Try / catch

try { downloader.download(c, progress, status, listener, noResume, allowCache); } catch (Exception e) { if (e.getMessage().contains("invalid filename or exinsting directory")) { cleanStagingAndRetry(); } else { throw e; } }

Prevention

When it happens

Trigger: Calling download() where contribution.getArchiveFileName() resolves (after stripping path components via File.getName() and normalize()) to a path under stagingFolder that already exists as a directory.

Common situations: A broken/partial previous download created a directory with the archive's name; a malformed package index supplies an archive name like '.' or a path-like string; tools or downloads share names with directories in the staging folder.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06). Data as JSON: /api/errors/860ea5d30cb1015b. Report an issue: GitHub.