{"record":{"id":"860ea5d30cb1015b","repo":"arduino/Arduino","slug":"can-t-download-0-invalid-filename-or-exinsting","errorCode":null,"errorMessage":"Can't download {0}: invalid filename or exinsting directory","messagePattern":"Can't download (.+?): invalid filename or exinsting directory","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java","lineNumber":65,"sourceCode":"\npublic class DownloadableContributionsDownloader {\n  private final File stagingFolder;\n\n  public DownloadableContributionsDownloader(File _stagingFolder) {\n    stagingFolder = _stagingFolder;\n  }\n\n  public File download(DownloadableContribution contribution, Progress progress, final String statusText, ProgressListener progressListener, boolean allowCache) throws Exception {\n    return download(contribution, progress, statusText, progressListener, false, allowCache);\n  }\n\n  public File download(DownloadableContribution contribution, Progress progress, final String statusText, ProgressListener progressListener, boolean noResume, boolean allowCache) throws Exception {\n    URL url = new URL(contribution.getUrl());\n    // Filter out paths from file name\n    String filename = new File(contribution.getArchiveFileName()).getName();\n    Path outputFile = Paths.get(stagingFolder.getAbsolutePath(), filename).normalize();\n    if (outputFile.toFile().isDirectory()) {\n      throw new Exception(format(\"Can't download {0}: invalid filename or exinsting directory\", contribution.getArchiveFileName()));\n    }\n\n    // Ensure the existence of staging folder\n    Files.createDirectories(stagingFolder.toPath());\n\n    if (!hasChecksum(contribution) && Files.exists(outputFile)) {\n      Files.delete(outputFile);\n    }\n\n    boolean downloaded = false;\n    while (true) {\n      // Need to download or resume downloading?\n      if (!Files.isRegularFile(outputFile, LinkOption.NOFOLLOW_LINKS) || (Files.size(outputFile) < contribution.getSize())) {\n        download(url, outputFile.toFile(), progress, statusText, progressListener, noResume, allowCache);\n        downloaded = true;\n      }\n\n      // Test checksum","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/arduino/Arduino/blob/a0df6e0e83b652c72bc78b0a1376c54d6ebc3bee/arduino-core/src/cc/arduino/contributions/DownloadableContributionsDownloader.java#L47-L83","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the staging folder and remove the directory that collides with the archive file name, then retry the download.","Check the package index URL / archive file name for the offending contribution and fix or update the index.","Clear the staging directory (e.g. ~/Arduino/staging) if its contents are in an inconsistent state.","Pre-validate the file name before calling download(): ensure it is a plain file name and not an existing directory path."],"exampleFix":"// before\ndownloader.download(contribution, progress, \"Downloading\", listener, false, true);\n// after\nString name = new File(contribution.getArchiveFileName()).getName();\nFile out = new File(stagingDir, name);\nif (out.isDirectory()) {\n  FileUtils.deleteDirectory(out); // or fail fast with a clear message\n}\ndownloader.download(contribution, progress, \"Downloading\", listener, false, true);","handlingStrategy":"validation","validationCode":"File out = new File(stagingFolder, new File(contribution.getArchiveFileName()).getName());\nif (out.isDirectory()) { throw new IllegalStateException(\"Staging path is a directory: \" + out); }","typeGuard":null,"tryCatchPattern":"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; } }","preventionTips":["Keep the staging folder free of directories named like archive files.","Sanitize archive file names from indexes before downloading.","After a crashed download, inspect staging for anomalous directories."],"tags":["arduino","download","filesystem","invalid-filename"],"backgroundTag":"invalid-argument-value","analyzedSha":"a0df6e0e83b652c72bc78b0a1376c54d6ebc3bee","analyzedAt":"2026-09-06T10:13:38.901Z","contentChangedAt":"2026-09-06T10:13:38.901Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}