HMCL-dev/HMCL · error · FileNotFoundException

File missing

Error message

File missing: ${artifact}

What it means

Thrown as FileNotFoundException when, after a processor claims to have succeeded (exit code 0), one of its declared output files (key of processor.getOutputs()) does not exist on disk. The processor silently failed to write its expected artifact.

Solutions

  1. Check the processor's log output in HMCL's log for silent errors
  2. Ensure the game directory and libraries directory are writable and the path isn't blocked by antivirus
  3. Free disk space and verify path length limits (Windows MAX_PATH)
  4. Delete any partially written outputs and re-run the installation
  5. Try installing into a simple path like C:\HMCL to rule out path/encoding problems
Defensive patterns

Strategy: try-catch

Validate before calling

// after running the processor, before trusting exit code 0:
for (String out : processor.getOutputs().keySet())
    if (!Files.exists(Paths.get(out))) triggerProcessorLogInspection();

Try / catch

try { task.run(); } catch (FileNotFoundException e) { if (e.getMessage().startsWith("File missing:")) cleanPartialOutputsAndRetry(); else throw e; }

Prevention

When it happens

Trigger: Iterating outputs after callExternalProcess returned 0; Paths.get(entry.getKey()) (the parsed output path) is not a regular file — processor wrote nothing, wrote to the wrong location, or something deleted the file between process exit and check.

Common situations: Processor aborted internally while still exiting 0; antivirus quarantined the freshly written file; insufficient write permissions in the target directory; path length/encoding issues on Windows; a stale output whose re-creation failed.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/e994eeb1062d881c. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java:158

            List<String> args = new ArrayList<>(processor.getArgs().size());
            for (String arg : processor.getArgs()) {
                String parsed = parseLiteral(arg, vars);
                if (parsed == null)
                    throw new ArtifactMalformedException("Invalid forge installation configuration");
                args.add(parsed);
            }

            command.addAll(args);

            LOG.info("Executing external processor " + processor.getJar().toString() + ", command line: " + new CommandBuilder().addAll(command).toString());
            int exitCode = SystemUtils.callExternalProcess(command);
            if (exitCode != 0)
                throw new IOException("Game processor exited abnormally with code " + exitCode);

            for (Map.Entry<String, String> entry : outputs.entrySet()) {
                Path artifact = Paths.get(entry.getKey());
                if (!Files.isRegularFile(artifact))
                    throw new FileNotFoundException("File missing: " + artifact);

                String code;
                try (InputStream stream = Files.newInputStream(artifact)) {
                    code = DigestUtils.digestToString("SHA-1", stream);
                }

                if (!Objects.equals(code, entry.getValue())) {
                    Files.delete(artifact);
                    throw new ChecksumMismatchException("SHA-1", entry.getValue(), code);
                }
            }
        }
    }

    private final DefaultDependencyManager dependencyManager;
    private final DefaultGameRepository gameRepository;
    private final GameInstanceManifest manifest;
    /// Source vanilla client JAR copied before processors are invoked.

View on GitHub (pinned to 24702dc5a0)