quarkusio/quarkus · error · UncheckedIOException

Unable to close InputStream for template: ${template}

Error message

Unable to close InputStream for template: ${template}

What it means

In getTemplate's finally block, closing the template InputStream throws, and the close failure is wrapped in UncheckedIOException 'Unable to close InputStream for template: <template>'. Rare; it replaces any pending success with a close-time error.

Source

Thrown at devtools/config-doc-maven-plugin/src/main/java/io/quarkus/maven/config/doc/GenerateConfigDocMojo.java:498

            is = Thread.currentThread().getContextClassLoader().getResourceAsStream(candidate);
            if (is != null) {
                break;
            }
        }

        if (is == null) {
            throw new IllegalArgumentException("Unable to find a template for these candidates " + candidates);
        }

        try {
            return new String(is.readAllBytes(), StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new UncheckedIOException("Unable to read the template: " + template, e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                throw new UncheckedIOException("Unable to close InputStream for template: " + template, e);
            }
        }
    }

    private static Set<String> collectDuplicatePropertyPaths(MergedModel mergedModel) {
        Set<String> seenBuildTime = new HashSet<>();
        Set<String> seenRunTime = new HashSet<>();

        for (Map<ConfigRootKey, ConfigRoot> configRoots : mergedModel.getConfigRoots().values()) {
            for (ConfigRoot configRoot : configRoots.values()) {
                collectPropertyPhases(configRoot, seenBuildTime, seenRunTime);
            }
        }
        for (ConfigRoot configRoot : mergedModel.getConfigRootsInSpecificFile().values()) {
            collectPropertyPhases(configRoot, seenBuildTime, seenRunTime);
        }
        for (List<ConfigSection> sections : mergedModel.getGeneratedConfigSections().values()) {
            for (ConfigSection section : sections) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Check the source jar/filesystem for corruption and rebuild or re-download it
  2. Retry the build; transient I/O close failures often disappear on rerun
  3. If a custom locator supplies the stream, ensure close() is safe and idempotent
Defensive patterns

Strategy: retry

Try / catch

try {
    mojo.execute();
} catch (UncheckedIOException e) {
    if (e.getMessage().startsWith("Unable to close InputStream")) {
        // transient I/O — log and retry the build once
    }
}

Prevention

When it happens

Trigger: is.close() throws IOException — typically when reading from a broken jar file system, an interrupted stream, or low-level I/O failure during close.

Common situations: Underlying jar/zip handle in a bad state; filesystem errors in containers with I/O pressure; classpath resource served over a flaky custom URL handler.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/d9bf1d23a08e05d6. Report an issue: GitHub.