{"record":{"id":"113941f470729423","repo":"elastic/elasticsearch","slug":"failed-to-unpack-with-checksum","errorCode":null,"errorMessage":"Failed to unpack {} with checksum {}","messagePattern":"Failed to unpack (.+?) with checksum (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"build-tools/src/main/java/org/elasticsearch/gradle/transform/UnpackTransform.java","lineNumber":100,"sourceCode":"    default void transform(TransformOutputs outputs) {\n        File archiveFile = getArchiveFile().get().getAsFile();\n        File extractedDir = outputs.dir(archiveFile.getName());\n\n        if (getParameters().getIncludeArtifactName().getOrElse(false)) {\n            extractedDir = new File(extractedDir, archiveFile.getName());\n        }\n\n        try {\n            LOGGER.info(\"Unpacking {} using {}.\", archiveFile.getName(), getClass().getSimpleName());\n            unpack(archiveFile, extractedDir, outputs, getParameters().getAsFiletreeOutput());\n        } catch (IOException e1) {\n            String hash = \"[unknown]\";\n            try {\n                hash = getSha1(archiveFile);\n            } catch (Exception e2) {\n                LOGGER.warn(\"Unable to calculate hash for file \" + archiveFile.getPath(), e2);\n            }\n            throw new UncheckedIOException(\"Failed to unpack \" + archiveFile.getName() + \" with checksum \" + hash, e1);\n        }\n    }\n\n    void unpack(File archiveFile, File targetDir, TransformOutputs outputs, boolean asFiletreeOutput) throws IOException;\n\n    default Function<String, Path> pathResolver() {\n        List<String> keepPatterns = getParameters().getKeepStructureFor();\n        String trimmedPrefixPattern = getParameters().getTrimmedPrefixPattern();\n        return trimmedPrefixPattern != null ? (i) -> trimArchiveExtractPath(keepPatterns, trimmedPrefixPattern, i) : (i) -> Path.of(i);\n    }\n\n    /*\n     * We want to be able to trim off certain prefixes when transforming archives.\n     *\n     * E.g We want to remove up to the and including the jdk-.* relative paths. That is a JDK archive is structured as:\n     *   jdk-12.0.1/\n     *   jdk-12.0.1/Contents\n     *   ...","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools/src/main/java/org/elasticsearch/gradle/transform/UnpackTransform.java#L82-L118","documentation":"UnpackTransform throws an UncheckedIOException wrapping the IOException from `unpack(...)` when extracting an archive (tar/zip) fails. Before throwing it computes a SHA-1 hash of the archive file (logging a warning if that also fails) and includes the archive name + hash in the message, so the exact failing artifact is identifiable in a dependency graph.","triggerScenarios":"A registered UnpackTransform (tar/zip extraction to a directory) fails because the archive is corrupt, truncated, of an unexpected format, password-protected, or the output directory can't be written.","commonSituations":"Corrupt or partially downloaded dependency archive; format mismatch (e.g. a `.tar.gz` declared as `.zip` or vice versa); disk full; the archive's checksum in the message lets you verify integrity against the published artifact.","solutions":["Verify the archive integrity: compare the printed SHA-1 against the published checksum, or re-download with `--refresh-dependencies`.","Clear the transform cache for that input (`./gradlew --rerun-tasks` or remove the specific transform output dir).","Confirm the unpack implementation matches the archive type (the abstract `unpack(...)` is implemented per format — check the concrete subclass used).","Check disk space and that the output directory is writable."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Verify archive integrity before relying on the transform\nString expected = publishedSha1(archiveFile.getName());\nString actual = sha1Of(archiveFile);\nif (!expected.equals(actual)) {\n  throw new IllegalStateException(\"Corrupt archive \" + archiveFile + \"; re-download.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  unpackTransform();\n} catch (UncheckedIOException e) {\n  if (e.getMessage().contains(\"Failed to unpack\")) {\n    // the message includes the sha1 — compare to the published checksum, then refresh deps\n  }\n  throw e;\n}","preventionTips":["Validate downloaded archives against published checksums in CI.","Use `--refresh-dependencies` after cache corruption or network errors.","Match the unpack implementation to the archive format declared in the transform."],"tags":["gradle","transform","io","dependencies","archives","build-tools"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}