elastic/elasticsearch · critical · IOException
missing composable template resource [{}]
Error message
missing composable template resource [{}] What it means
Thrown as IOException by KibanaPlugin.loadDataStreamComposableTemplate when the named template resource file cannot be found on the plugin's classpath (getResourceAsStream returns null). This is a plugin packaging/build defect, not a user input error: the kibana module ships composable index-template JSON under org/elasticsearch/kibana/ and this fires if a referenced file is absent from the jar.
Source
Thrown at modules/kibana/src/main/java/org/elasticsearch/kibana/KibanaPlugin.java:270
);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/**
* Loads a composable template from {@code org/elasticsearch/kibana/} resources with {@code ${variable}} substitution
* using the same semantics as {@code org.elasticsearch.xpack.core.template.TemplateUtils}.
* <p>
* Templates live in this module (not {@code x-pack} template-resources) so {@code org.elasticsearch.kibana} does not
* {@code require org.elasticsearch.xcore}. That {@code requires} breaks JPMS plugin layer resolution: the kibana module
* resolves in a layer where {@code org.elasticsearch.xcore} is not on the module path (see {@code PluginsLoader}).
*/
private static ComposableIndexTemplate loadDataStreamComposableTemplate(String resourceFileName, Map<String, String> variables)
throws IOException {
try (InputStream in = KibanaPlugin.class.getResourceAsStream(resourceFileName)) {
if (in == null) {
throw new IOException("missing composable template resource [" + resourceFileName + "]");
}
String raw = new String(in.readAllBytes(), StandardCharsets.UTF_8);
String source = substituteTemplateVariables(raw, variables);
try (
var parser = JsonXContent.jsonXContent.createParser(
XContentParserConfiguration.EMPTY,
source.getBytes(StandardCharsets.UTF_8)
)
) {
return ComposableIndexTemplate.parse(parser);
}
}
}
/** Same substitution semantics as {@code TemplateUtils.replaceVariables}. */
private static String substituteTemplateVariables(String input, Map<String, String> variables) {
String template = input;
for (Map.Entry<String, String> variable : variables.entrySet()) {View on GitHub (pinned to db6a809a66)
Solutions
- Verify the resource file exists under modules/kibana/src/main/resources/org/elasticsearch/kibana/ and matches the name passed in.
- Rebuild the kibana module cleanly (./gradlew :modules:kibana:assemble) to ensure resources are packaged.
- If the filename was renamed, update the caller in KibanaPlugin to reference the new name.
Example fix
// before: file is kibana-data-stream.json but code asks for kibana-template.json
loadDataStreamComposableTemplate("kibana-template.json", vars)
// after: align the name with the actual resource file
loadDataStreamComposableTemplate("kibana-data-stream.json", vars) Defensive patterns
Strategy: validation
Validate before calling
// In plugin/build code, assert the resource exists at startup
String res = "org/elasticsearch/kibana/" + resourceFileName;
try (var in = KibanaPlugin.class.getResourceAsStream(res)) {
if (in == null) throw new IllegalStateException("Missing template resource: " + res);
} Try / catch
// Wrap template loading so startup fails fast with a clear message
try {
loadDataStreamComposableTemplate(name, vars);
} catch (IOException e) {
throw new RuntimeException("kibana template resource missing: " + name, e);
} Prevention
- Keep template filenames and the constants referencing them in sync; rename atomically.
- Run a full :modules:kibana:assemble and smoke-test startup after resource changes.
- Do not exclude src/main/resources when packaging the plugin jar.
When it happens
Trigger: Plugin startup or feature initialization calls loadDataStreamComposableTemplate(resourceFileName) and the file is missing from the classpath. Happens after a build that failed to include the resource, a rename of the template file without updating the caller, or a corrupt/incomplete plugin jar.
Common situations: Custom build of the kibana module that excluded resources; renaming a .json template file but not the constant referencing it; packaging the plugin without src/main/resources; deploying a partial/manually-assembled jar.
Related errors
- Unable to locate {} on build classpath.
- unknown scheme:{rootURI.getScheme()}
- Classpath should not contain empty elements! (outdated shell
- jar hell! duplicate jar [{element}] on classpath: {classPath
- jar hell! duplicate jar on classpath: {path}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/6931b883b1142473.
Report an issue: GitHub.