quarkusio/quarkus · error · UncheckedIOException
Unable to scan: ${next}
Error message
Unable to scan: ${next} What it means
WatchServiceFileSystemWatcher.doScan walks registered directories to snapshot last-modified times; if Files.list or getLastModifiedTime throws IOException for any path, it is rethrown as UncheckedIOException 'Unable to scan: <path>'. It means the dev-mode change scanner cannot read a directory it was asked to watch.
Source
Thrown at core/deployment/src/main/java/io/quarkus/deployment/dev/filesystem/watch/WatchServiceFileSystemWatcher.java:250
watchService.close();
}
}
private static Map<Path, Long> doScan(Path directory) {
final Map<Path, Long> results = new HashMap<>();
final Deque<Path> toScan = new ArrayDeque<>();
toScan.add(directory);
while (!toScan.isEmpty()) {
Path next = toScan.pop();
if (Files.isDirectory(next)) {
try {
results.put(next, Files.getLastModifiedTime(directory).toMillis());
try (Stream<Path> list = Files.list(next)) {
list.forEach(p -> toScan.push(p.toAbsolutePath()));
}
} catch (IOException e) {
throw new UncheckedIOException("Unable to scan: " + next, e);
}
}
}
return results;
}
private static void invokeCallback(FileChangeCallback callback, List<FileChangeEvent> results) {
try {
callback.handleChanges(results);
} catch (Exception e) {
log.error("Failed to invoke watch callback", e);
}
}
private class PathData {
private final Path path;
private final List<FileChangeCallback> callbacks = new ArrayList<>();View on GitHub (pinned to e1c734241f)
Solutions
- Check the path named in the message: restore it, remove broken symlinks, or fix permissions
- Run git clean/reset or restart quarkus:dev after mass file operations like branch switches
- Raise the open-file limit (ulimit -n) if 'Too many open files' appears as the cause
- Exclude volatile paths (node_modules, generated dirs) from watching if applicable
Example fix
// before: branch switch removes watched dir, scan fails // after: restart dev mode after large checkouts, or fix path rm -rf node_modules && npm ci # recreate missing/legacy paths ulimit -n 4096
Defensive patterns
Strategy: validation
Validate before calling
for (Path dir : watchedDirs) {
if (!Files.isReadable(dir)) throw new IllegalStateException("Watched dir not readable: " + dir);
if (Files.isSymbolicLink(dir) && !Files.exists(dir.toRealPath())) throw new IllegalStateException("Broken symlink: " + dir);
} Try / catch
try {
watcher.scan();
} catch (UncheckedIOException e) {
if (e.getMessage().startsWith("Unable to scan:")) {
Path bad = Path.of(e.getMessage().replace("Unable to scan: ", ""));
// re-register or skip the missing directory, then rescan
}
throw e;
} Prevention
- Avoid branch switches/cleans that delete watched directories during live reload; restart dev mode afterwards
- Keep ulimit -n high enough for many open directory streams
- Remove broken symlinks from the project tree
When it happens
Trigger: allDirectories() -> doScan() iterating watched dirs when a directory disappears (deleted during scan), permission is denied, or a symlink is broken.
Common situations: A watched directory deleted while dev mode runs (clean, git checkout/branch switch); permission changes; too many open files (ulimit) breaking Files.list; broken symlinks in the project tree.
Related errors
- Cannot create directory ${directory}
- Failed to create output directory for generated sources: %s
- ${archiveRoot} does not point to the application output dire
- Unable to deserialize the dev mode context. Does the Quarkus
- Hot deployment of the application is not supported when upda
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/037c270eabe12677.
Report an issue: GitHub.