elastic/elasticsearch · error · IllegalArgumentException

Failed to read {} as UTF_8

Error message

Failed to read {} as UTF_8

What it means

Thrown by ForbiddenPatternsTask.checkInvalidPatterns when Files.lines on a source file raises UncheckedIOException (wrapping an IOException). The task reads every checked file as UTF-8 to scan for forbidden patterns; a file that cannot be read/decoded aborts the scan with this IllegalArgumentException.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ForbiddenPatternsTask.java:125

    public FileCollection getFiles() {
        return getSourceFolders().get()
            .stream()
            .map(sourceFolder -> sourceFolder.matching(filesFilter))
            .reduce(FileTree::plus)
            .orElse(projectLayout.files().getAsFileTree());
    }

    @TaskAction
    public void checkInvalidPatterns() throws IOException {
        Pattern allPatterns = Pattern.compile("(" + String.join(")|(", getPatterns().values()) + ")");
        List<Problem> problems = new ArrayList<>();
        List<String> violations = new ArrayList<>();
        for (File f : getFiles()) {
            List<String> lines;
            try (Stream<String> stream = Files.lines(f.toPath(), StandardCharsets.UTF_8)) {
                lines = stream.collect(Collectors.toList());
            } catch (UncheckedIOException e) {
                throw new IllegalArgumentException("Failed to read " + f + " as UTF_8", e);
            }

            URI baseUri = getRootDir().orElse(projectLayout.getProjectDirectory().getAsFile()).get().toURI();
            String path = baseUri.relativize(f.toURI()).toString();
            String absolutePath = f.getAbsolutePath();
            IntStream.range(0, lines.size())
                .filter(i -> allPatterns.matcher(lines.get(i)).find())
                .mapToObj(l -> new AbstractMap.SimpleEntry<>(l + 1, lines.get(l)))
                .forEach(
                    kv -> patterns.entrySet()
                        .stream()
                        .filter(p -> Pattern.compile(p.getValue()).matcher(kv.getValue()).find())
                        .forEach(p -> {
                            int lineNumber = kv.getKey();
                            String ruleName = p.getKey();
                            String label = ruleName + " on line " + lineNumber + " of " + path;
                            violations.add("- " + label);
                            problems.add(

View on GitHub (pinned to db6a809a66)

Solutions

  1. Open the wrapped UncheckedIOException to find the failing file and root cause.
  2. If the file is non-UTF-8, convert it to UTF-8 (iconv -f LATIN1 -t UTF-8 file) or add it to the task's exclude filter.
  3. If the file was deleted mid-build, ensure sources are stable before the task runs (proper task dependencies).
  4. Fix filesystem permissions / remount if the cause is I/O.

Example fix

# before: file is Latin-1 encoded
# after
iconv -f LATIN1 -t UTF-8 src/main/resources/legacy.txt -o src/main/resources/legacy.txt
Defensive patterns

Strategy: validation

Validate before calling

// Confirm files are readable UTF-8 before scanning
for (File f : getFiles()) {
    if (!f.isFile()) throw new IllegalArgumentException("Missing file: " + f);
    try { Files.readString(f.toPath(), StandardCharsets.UTF_8); }
    catch (IOException e) { throw new IllegalArgumentException("Not UTF-8 / unreadable: " + f, e); }
}

Try / catch

try (Stream<String> s = Files.lines(f.toPath(), StandardCharsets.UTF_8)) {
    ...
} catch (IllegalArgumentException e) {
    if (e.getCause() instanceof UncheckedIOException) {
        // convert the file to UTF-8 or exclude it, then re-run
    }
    throw e;
}

Prevention

When it happens

Trigger: A file in getFiles() that does not exist at read time, is not readable, or contains bytes that break the UTF-8 decoder under Files.lines.

Common situations: A source file deleted between configuration and execution; a file containing non-UTF-8 bytes (legacy Latin-1); a file on a network mount that became unreachable; permission issues.

Related errors


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