elastic/elasticsearch · error · GradleException

Cannot generate source from String template

Error message

Cannot generate source from String template

What it means

Thrown by StringTemplateTask.generate when an IOException occurs while rendering a StringTemplate (ST) template and writing the generated file. The task reads the input template, injects properties via st.add, renders with st.render(), normalizes CRLF to LF, creates parent directories, and writes the output; any I/O failure in that sequence is wrapped in this GradleException. Note ST's own template-syntax errors throw STException (a RuntimeException), not IOException — this catch specifically covers filesystem/encoding I/O.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/StringTemplateTask.java:93

                ST st = new ST(Files.readString(spec.inputFile.toPath(), UTF_8), '$', '$');
                for (var entry : spec.properties.entrySet()) {
                    if (entry.getValue().isEmpty()) {
                        st.add(entry.getKey(), null);
                    } else {
                        st.add(entry.getKey(), entry.getValue());
                    }
                }
                // ST's default AutoIndentWriter renders newlines using the platform's
                // line.separator, so on Windows the output is CRLF regardless of the
                // input template's own (LF) line endings. Normalize to LF explicitly so
                // generated sources are consistent across OSes and match what spotless
                // (configured with LineEnding.UNIX) expects.
                String output = st.render().replace("\r\n", "\n");
                Files.createDirectories(outputRootFolder.toPath().resolve(spec.outputFile).getParent());
                Files.writeString(new File(outputRootFolder, spec.outputFile).toPath(), output, UTF_8);
                getLogger().info("StringTemplateTask generated {}", spec.outputFile);
            } catch (IOException e) {
                throw new GradleException("Cannot generate source from String template", e);
            }
        }
    }

    class TemplateSpec {
        private File inputFile;

        private String outputFile;

        private Map<String, String> properties;

        @InputFile
        @PathSensitive(PathSensitivity.RELATIVE)
        public File getInputFile() {
            return inputFile;
        }

        public void setInputFile(File inputFile) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify spec.inputFile exists and is readable (check the task's input file configuration and the logged 'StringTemplateTask generating {}' line just before the failure).
  2. Ensure getOutputFolder() resolves to a writable directory and that no regular file occupies a needed parent path.
  3. Check filesystem permissions and free space on the output volume.
  4. If running on Windows and the file is locked, close the holder (IDE/antivirus) or rerun.
  5. Distinguish from ST syntax errors: a template-parse failure surfaces as org.stringtemplate.v4.STException, not this message — fix the template delimiters ($...$) if that is the actual cause.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight before the task runs:
import java.nio.file.*;
Path in = spec.inputFile.toPath();
if (!Files.isReadable(in)) throw new IllegalArgumentException("unreadable template: " + in);
Path outDir = outputFolder.getAsFile().get().toPath();
Path outParent = outDir.resolve(spec.outputFile).getParent();
if (Files.exists(outParent) && !Files.isDirectory(outParent))
    throw new IllegalArgumentException("output parent is not a directory: " + outParent);
if (!Files.isWritable(outParent))
    throw new IllegalArgumentException("output dir not writable: " + outParent);

Try / catch

try {
    st.add(...); st.render(); Files.writeString(...);
} catch (java.io.IOException e) {
    throw new GradleException("Cannot generate source from String template for "
        + spec.inputFile + " -> " + spec.outputFile, e);
}

Prevention

When it happens

Trigger: Inside the per-template try block: Files.readString(spec.inputFile.toPath()) fails (input missing/unreadable), st.render() is fine but Files.createDirectories(...) fails (permission/disk), or Files.writeString(...) fails (output path unwritable, parent is a file not a directory). The catch is narrow: catch (IOException e).

Common situations: The configured inputFile does not exist or is not readable; the outputFolder points to a read-only location or a path whose parent is a regular file; disk full or permissions denied during write; the output directory was deleted out from under the task; the input file is locked by another process on Windows.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/a2685a4e639e0473. Report an issue: GitHub.