{"record":{"id":"e994eeb1062d881c","repo":"HMCL-dev/HMCL","slug":"file-missing-artifact","errorCode":null,"errorMessage":"File missing: ${artifact}","messagePattern":"File missing: (.+?)","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java","lineNumber":158,"sourceCode":"            List<String> args = new ArrayList<>(processor.getArgs().size());\n            for (String arg : processor.getArgs()) {\n                String parsed = parseLiteral(arg, vars);\n                if (parsed == null)\n                    throw new ArtifactMalformedException(\"Invalid forge installation configuration\");\n                args.add(parsed);\n            }\n\n            command.addAll(args);\n\n            LOG.info(\"Executing external processor \" + processor.getJar().toString() + \", command line: \" + new CommandBuilder().addAll(command).toString());\n            int exitCode = SystemUtils.callExternalProcess(command);\n            if (exitCode != 0)\n                throw new IOException(\"Game processor exited abnormally with code \" + exitCode);\n\n            for (Map.Entry<String, String> entry : outputs.entrySet()) {\n                Path artifact = Paths.get(entry.getKey());\n                if (!Files.isRegularFile(artifact))\n                    throw new FileNotFoundException(\"File missing: \" + artifact);\n\n                String code;\n                try (InputStream stream = Files.newInputStream(artifact)) {\n                    code = DigestUtils.digestToString(\"SHA-1\", stream);\n                }\n\n                if (!Objects.equals(code, entry.getValue())) {\n                    Files.delete(artifact);\n                    throw new ChecksumMismatchException(\"SHA-1\", entry.getValue(), code);\n                }\n            }\n        }\n    }\n\n    private final DefaultDependencyManager dependencyManager;\n    private final DefaultGameRepository gameRepository;\n    private final GameInstanceManifest manifest;\n    /// Source vanilla client JAR copied before processors are invoked.","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/neoforge/NeoForgeOldInstallTask.java#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the processor's log output in HMCL's log for silent errors","Ensure the game directory and libraries directory are writable and the path isn't blocked by antivirus","Free disk space and verify path length limits (Windows MAX_PATH)","Delete any partially written outputs and re-run the installation","Try installing into a simple path like C:\\HMCL to rule out path/encoding problems"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// after running the processor, before trusting exit code 0:\nfor (String out : processor.getOutputs().keySet())\n    if (!Files.exists(Paths.get(out))) triggerProcessorLogInspection();","typeGuard":null,"tryCatchPattern":"try { task.run(); } catch (FileNotFoundException e) { if (e.getMessage().startsWith(\"File missing:\")) cleanPartialOutputsAndRetry(); else throw e; }","preventionTips":["Treat exit code 0 as necessary but not sufficient; verify outputs (the task already SHA-1 checks them)","Ensure write permissions and path-length headroom on Windows","Whitelist the game directory in antivirus software","Install into a simple, ASCII, short path"],"tags":["file-not-found","installer","output-artifact","external-process"],"backgroundTag":"file-not-found","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}