HMCL-dev/HMCL · error · ArtifactMalformedException
Expecting file in terracotta bundle.
Error message
Expecting %s file in terracotta bundle.
What it means
TerracottaBundle.install verifies every expected file listed in the bundle manifest exists inside the extracted tar tree before writing it to disk. If an entry is missing from the archive, ArtifactMalformedException is thrown, indicating the downloaded terracotta bundle is incomplete or corrupt.
Solutions
- Re-download the terracotta bundle to replace the corrupt/partial archive
- Verify the archive against its published checksum before installing
- Ensure the download URL points to a real tar bundle, not an error page or HTML proxy response
- Report/refresh the upstream bundle so manifest and archive contents match
Defensive patterns
Strategy: validation
Validate before calling
// verify archive contains every manifest entry before install
for (String file : manifest.keySet()) { if (tree.getEntry("/" + file) == null) throw new IllegalArgumentException("missing entry: " + file); } Try / catch
try { bundle.install(root); } catch (ArtifactMalformedException e) { Files.walk(root).sorted(Comparator.reverseOrder()).forEach(Files::deleteIfExists); /* re-download */ } Prevention
- Validate bundle checksum after download and before install
- Use resumable, verified downloads on unstable networks
- Keep bundle manifest and archive generated by the same build
When it happens
Trigger: A downloaded bundle whose tar archive lacks a file referenced by its manifest — truncated download, CDN proxy serving an error page repackaged as tar, or a mismatched manifest/archive pair.
Common situations: Flaky network causing partial downloads; intermediary proxies injecting HTML error pages; publishing a bundle with a stale manifest.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- File has incorrect SHA-1 hash: expected , got
- Remote response metadata is unavailable
- Failed to download texture
- Failed to download theme background: HTTP
- Unsupported checksum type:
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/c94e593cf2c9d1ea.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaBundle.java:121
context.bindProgress(download.progressProperty());
return download.thenSupplyAsync(() -> pkg);
});
}
public Task<?> install(Path pkg) {
return Task.runAsync(() -> {
Files.createDirectories(root);
FileUtils.cleanDirectory(root);
try (TarFileTree tree = TarFileTree.open(pkg)) {
for (Map.Entry<String, FileDownloadTask.IntegrityCheck> entry : files.entrySet()) {
String file = entry.getKey();
FileDownloadTask.IntegrityCheck check = entry.getValue();
Path path = root.resolve(file);
TarArchiveEntry archive = tree.getEntry("/" + file);
if (archive == null) {
throw new ArtifactMalformedException(String.format("Expecting %s file in terracotta bundle.", file));
}
MessageDigest digest = DigestUtils.getDigest(check.algorithm());
try (
InputStream is = tree.getInputStream(archive);
OutputStream os = new DigestOutputStream(Files.newOutputStream(path), digest)
) {
is.transferTo(os);
}
String hash = HexFormat.of().formatHex(digest.digest());
if (!check.checksum().equalsIgnoreCase(hash)) {
throw new ChecksumMismatchException(check.algorithm(), check.checksum(), hash);
}
switch (OperatingSystem.CURRENT_OS) {
case LINUX, MACOS, FREEBSD -> Files.setPosixFilePermissions(path, FileUtils.parsePosixFilePermission(archive.getMode()));
}View on GitHub (pinned to 24702dc5a0)