quarkusio/quarkus · error · UncheckedIOException
Unable to read ${resourceName} from ${path}
Error message
Unable to read ${resourceName} from ${path} What it means
Channels.streamFor resolves a resource by name (classloader resource) and falls back to opening it as a file path. When neither the classloader resource exists nor Files.newInputStream(path) succeeds (file missing, unreadable, is a directory), the IOException is wrapped into an UncheckedIOException with the message 'Unable to read <resourceName> from <path>'. This is used e.g. for loading certificate/authority material when building gRPC channels.
Source
Thrown at extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/Channels.java:268
}
private static Buffer bufferFor(Path path, String resourceName) throws IOException {
try (InputStream stream = streamFor(path, resourceName)) {
return Buffer.buffer(stream.readAllBytes());
}
}
private static InputStream streamFor(Path path, String resourceName) {
final InputStream resource = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(ClassPathUtils.toResourceName(path));
if (resource != null) {
return resource;
} else {
try {
return Files.newInputStream(path);
} catch (IOException e) {
throw new UncheckedIOException("Unable to read " + resourceName + " from " + path, e);
}
}
}
@SuppressWarnings("unchecked")
public static Channel retrieveChannel(String name, Set<String> perClientInterceptors) {
ClientInterceptorStorage clientInterceptorStorage = Arc.container().instance(ClientInterceptorStorage.class).get();
Annotation[] qualifiers = new Annotation[perClientInterceptors.size() + 1];
int idx = 0;
qualifiers[idx++] = GrpcClient.Literal.of(name);
for (String interceptor : perClientInterceptors) {
qualifiers[idx++] = RegisterClientInterceptor.Literal
.of((Class<? extends ClientInterceptor>) clientInterceptorStorage.getPerClientInterceptor(interceptor));
}
InstanceHandle<Channel> instance = Arc.container().instance(Channel.class, qualifiers);
if (!instance.isAvailable()) {
throw new IllegalStateException("Unable to retrieve the gRPC Channel " + name);
}View on GitHub (pinned to e1c734241f)
Solutions
- Verify the path exists and is readable at runtime (ls/stat the exact path the process sees, including working directory for relative paths).
- Put the file under src/main/resources so it ships as a classpath resource, and reference it by resource name only.
- For native images/container builds, include the file (quarkus.native.resources.includes or volume mount) and use an absolute path.
- Check file permissions for the user running the Quarkus process.
Example fix
// before quarkus.grpc.clients.hello.trust-store.pem.paths=./ca.pem // not packaged // after # copy ca.pem to src/main/resources/certs/ca.pem quarkus.grpc.clients.hello.trust-store.pem.paths=certs/ca.pem
Defensive patterns
Strategy: validation
Validate before calling
// ensure the trust/key material is resolvable before configuring the client
String path = "certs/ca.pem";
boolean asResource = Thread.currentThread().getContextClassLoader().getResource(path) != null
|| Channels.class.getClassLoader().getResource(path) != null;
boolean asFile = java.nio.file.Files.isRegularFile(java.nio.file.Path.of(path))
&& java.nio.file.Files.isReadable(java.nio.file.Path.of(path));
if (!asResource && !asFile) {
throw new IllegalStateException("Resource/file not found or unreadable: " + path);
} Try / catch
try {
channel = Channels.createChannel("hello", interceptors);
} catch (UncheckedIOException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unable to read")) {
throw new ConfigurationException("Package the resource into the app (src/main/resources) or fix the path: " + e.getMessage(), e);
}
throw e;
} Prevention
- Ship certificate material as classpath resources under src/main/resources.
- For native images, register files via quarkus.native.resources.includes.
- Use absolute paths when loading from the filesystem and verify readability as the runtime user.
When it happens
Trigger: Configuring a gRPC client (e.g. trust-store / key-store path or SSL material) with a path/resource name that neither matches a classpath resource nor an existing readable file, so streamFor('name', 'path') fails on both branches during channel creation.
Common situations: Typo in the certificate path; file present in dev but not packaged into the native image or container; relative path resolved against a different working directory at runtime; file permissions deny read for the running user.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Failed to read %s
- Failed to read resources from classpath
- Could not read class path resources having path '${resourceP
- Failed to load + pomPropsPath + from the classpath
- Failed to load <pomPropsPath> from the classpath
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/82d0a8abc1e17360.
Report an issue: GitHub.