HMCL-dev/HMCL · error · java.io.IOException

Remote response metadata is unavailable

Error message

Remote response metadata is unavailable

What it means

CacheFileTask.getContext() needs some way to verify the downloaded content: either a pre-configured expected SHA-1 or the remote response's metadata (ETag). This IOException is thrown when expectedSha1 is null AND (the caller asked for ETag checking while the response info is null), meaning no integrity reference is available.

Solutions

  1. Call setExpectedSha1(...) on the task with the known SHA-1 of the artifact before executing
  2. Ensure the download URL is an HTTP(S) source that returns response headers so UrlResponseInfo is populated
  3. Check that the network client is not returning null response info for your transport (e.g. non-HTTP protocols)
  4. If no verification is possible, do not use the cache-verified variant of the task

Example fix

// before
CacheFileTask task = new CacheFileTask(url, file, null);
// after
task.setExpectedSha1(knownSha1);
CacheFileTask task = new CacheFileTask(url, file, knownSha1);
Defensive patterns

Strategy: try-catch

Validate before calling

if (expectedSha1 == null) {
    // ensure a checksum is configured before running the task
    task.setExpectedSha1(computeOrFetchKnownSha1(artifact));
}

Try / catch

try {
    cacheFileTask.run();
} catch (IOException e) {
    if (e.getMessage().contains("Remote response metadata is unavailable"))
        configureSha1AndRetry();
    else throw e;
}

Prevention

When it happens

Trigger: Running a CacheFileTask without calling setExpectedSha1(), while the underlying network layer returns a null UrlResponseInfo (e.g. non-HTTP download path or missing response) with checkETag=true, or checkETag=false with no expectedSha1.

Common situations: Configuring a cached download without a checksum against a source that does not supply response metadata; network layer short-circuits and returns null response info; refactors that drop the expectedSha1 configuration.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/task/CacheFileTask.java:141

        return EnumCheckETag.CHECK_E_TAG;
    }

    @Override
    protected void useCachedResult(Path cache) {
        setResult(cache);
    }

    /// Creates a temporary sink that publishes a successful download to the cache repository.
    ///
    /// @param response     the HTTP response metadata
    /// @param checkETag    whether remote cache metadata is being checked
    /// @param bmclapiHash  the hash supplied by BMCLAPI, or `null`
    /// @return the temporary download sink
    /// @throws IOException if the temporary file cannot be created
    @Override
    protected Context getContext(@Nullable UrlResponseInfo response, boolean checkETag, @Nullable String bmclapiHash) throws IOException {
        if (expectedSha1 == null && (!checkETag || response == null)) {
            throw new IOException("Remote response metadata is unavailable");
        }

        return new Context() {
            private final Path temp = Files.createTempFile("hmcl-download-", null);
            private final FileChannel fileOutput = FileChannel.open(temp,
                    StandardOpenOption.WRITE,
                    StandardOpenOption.TRUNCATE_EXISTING,
                    StandardOpenOption.CREATE);

            @Override
            public void reset() throws IOException {
                fileOutput.truncate(0L);
            }

            @Override
            public void write(byte[] buffer, int offset, int len) throws IOException {
                ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, offset, len);
                while (byteBuffer.hasRemaining()) {

View on GitHub (pinned to 24702dc5a0)