provectus/kafka-ui · error · ValidationException
proto files directory not readable
Error message
proto files directory not readable
What it means
ProtobufFileSerde's nested ProtoSchemaLoader resolves the configured base directory for .proto files and immediately checks readability. If the path does not exist or the kafka-ui process lacks read permission, ValidationException('proto files directory not readable') is thrown at configuration time.
Solutions
- Fix the configured directory path to point at an existing directory
- chmod/chown the directory so the kafka-ui process user can read it, or run the container with the right volume mount
- Verify inside the container (ls on the path) that the directory is visible and readable
Example fix
// before
serde:
protobufFileSerde:
descriptorPaths: /proto # not mounted
// after
serde:
protobufFileSerde:
descriptorPaths: /etc/kafka-ui/proto # exists & readable
# shell: chmod o+rx /etc/kafka-ui/proto Defensive patterns
Strategy: validation
Validate before calling
Path dir = Path.of(baseLocationStr); if (!Files.isDirectory(dir) || !Files.isReadable(dir)) throw new IllegalArgumentException("proto dir missing/unreadable: " + dir); Type guard
boolean isReadableDir(String p) { Path d = Path.of(p); return Files.isDirectory(d) && Files.isReadable(d); } Try / catch
try { new ProtoSchemaLoader(path); } catch (ValidationException e) { alert("proto dir unreadable: " + path); } Prevention
- Mount proto directories as read-only volumes and verify in the container image
- Use absolute paths in descriptorPaths
- Add a startup health check that stats the proto directory
When it happens
Trigger: Constructing ProtoSchemaLoader with a baseLocationStr whose Path is unreadable — nonexistent directory, wrong mount, or file-system permissions denying the process access.
Common situations: Descriptor paths mounted in a container but the volume not mounted in the kafka-ui pod; directory owned by another user; typo in the path or relative path resolved against an unexpected working directory.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- File already exists and is not writable
- Location does not exist
- No archive files were found
- Neither default, not per-topic descriptors defined for
- Dynamic file path is a directory, but should be a file path
AI-assisted analysis of provectus/kafka-ui@83b5a60cc0 (2026-09-08).
Data as JSON: /api/errors/dded61950af6c259.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-ui-api/src/main/java/com/provectus/kafka/ui/serdes/builtin/ProtobufFileSerde.java:315
}
private static void addProtobufSchemas(Map<Descriptor, Path> descriptorPaths,
Map<Path, ProtobufSchema> protobufSchemas,
Map<String, String> messageNamesByTopic) {
messageNamesByTopic.values().stream()
.map(msgName -> getDescriptorAndPath(protobufSchemas, msgName))
.forEach(entry -> descriptorPaths.put(entry.getKey(), entry.getValue()));
}
}
static class ProtoSchemaLoader {
private final Path baseLocation;
ProtoSchemaLoader(String baseLocationStr) {
this.baseLocation = Path.of(baseLocationStr);
if (!Files.isReadable(baseLocation)) {
throw new ValidationException("proto files directory not readable");
}
}
List<ProtoFile> load() {
Map<String, ProtoFile> knownTypes = knownProtoFiles();
Map<String, ProtoFile> filesByLocations = new HashMap<>();
filesByLocations.putAll(knownTypes);
filesByLocations.putAll(loadFilesWithLocations());
Linker linker = new Linker(
createFilesLoader(filesByLocations),
new ErrorCollector(),
true,
true
);
var schema = linker.link(filesByLocations.values());
linker.getErrors().throwIfNonEmpty();View on GitHub (pinned to 83b5a60cc0)