elastic/elasticsearch · error · UncheckedIOException

Failed to read OCI image layout index [{indexJson}]

Error message

Failed to read OCI image layout index [{indexJson}]

What it means

Thrown by DockerBuildTask.resolveBuildContext() when reading the OCI layout's index.json throws an IOException (the digest-search step from error 218 proceeds only after a successful read). The IOException is wrapped in an UncheckedIOException naming the index.json path. This is the I/O-level failure counterpart to error 218's content-level failure.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/docker/DockerBuildTask.java:349

         * manifest digest from {@code index.json} is the most robust way to reference the
         * (single-image) layouts we export.
         */
        private static String resolveBuildContext(String value) {
            String prefix = "oci-layout://";
            if (value.startsWith(prefix) == false || value.contains("@")) {
                return value;
            }
            Path indexJson = Path.of(value.substring(prefix.length()), "index.json");
            try {
                // The exported layouts contain a single manifest, so plucking the first digest is
                // sufficient and avoids a JSON parser dependency in this worker action.
                Matcher matcher = Pattern.compile("sha256:[a-f0-9]{64}").matcher(Files.readString(indexJson));
                if (matcher.find() == false) {
                    throw new GradleException("No manifest digest found in OCI image layout index [" + indexJson + "]");
                }
                return value + "@" + matcher.group();
            } catch (IOException e) {
                throw new UncheckedIOException("Failed to read OCI image layout index [" + indexJson + "]", e);
            }
        }

        private boolean isCrossPlatform() {
            return getParameters().getPlatforms()
                .get()
                .stream()
                .anyMatch(any -> any.equals(Architecture.current().dockerPlatform) == false);
        }

        private String getImageChecksum(String imageTag) {
            final ByteArrayOutputStream stdout = new ByteArrayOutputStream();
            String docker = getParameters().getDockerExecutable().get();

            execOperations.exec(spec -> {
                spec.setCommandLine(docker, "inspect", "--format", "{{ .Id }}", imageTag);
                spec.setStandardOutput(stdout);
                spec.setIgnoreExitValue(false);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Confirm the index.json at the reported path exists and is readable: `ls -l <indexJson>`.
  2. Re-run the task that produces/exports the OCI layout so the directory and index.json are created.
  3. Check the `oci-layout://<path>` value in the build config for typos or stale paths.
  4. Verify filesystem permissions for the build user.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before building, assert index.json exists and is readable:
// if (!Files.isReadable(indexJson)) fail("unreadable OCI index: " + indexJson);

Try / catch

// try { String json = Files.readString(indexJson); /* search digest */ }
// catch (IOException e) { throw new UncheckedIOException("Failed to read OCI image layout index [" + indexJson + "]", e); }

Prevention

When it happens

Trigger: Files.readString(indexJson) throws IOException while resolving an `oci-layout://` build context. Causes: index.json does not exist (the layout directory is missing or incomplete); it is a directory rather than a file; permission denied; filesystem/mount error; the path resolved from the `oci-layout://` prefix is invalid.

Common situations: The OCI layout export task did not run or failed, so the directory/index.json is absent; a path typo in the `oci-layout://` value points at a non-existent directory; running on a CI worker where the layout artifact was not materialized; permissions mismatch.

Related errors


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