skylot/jadx · error · JadxRuntimeException
Failed to build hash for inputs
Error message
Failed to build hash for inputs
What it means
Thrown by buildInputsHash(List<Path>) which computes an MD5 over the sorted input files' modification timestamps. The method expands directories, sorts, reads Files.getLastModifiedTime for each file, and writes timestamps to a DataOutputStream. Failure means: a file in the expanded list does not exist when getLastModifiedTime is called (NoSuchFileException — a race if files are deleted during hashing), an I/O error reading timestamps, or expandDirs encountered an inaccessible path.
Source
Thrown at jadx-core/src/main/java/jadx/core/utils/files/FileUtils.java:521
}
/**
* Hash timestamps of input files
*/
public static String buildInputsHash(List<Path> inputPaths) {
try (ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream data = new DataOutputStream(bout)) {
List<Path> inputFiles = FileUtils.expandDirs(inputPaths);
Collections.sort(inputFiles);
data.write(inputPaths.size());
data.write(inputFiles.size());
for (Path inputFile : inputFiles) {
FileTime modifiedTime = Files.getLastModifiedTime(inputFile);
data.writeLong(modifiedTime.toMillis());
}
return FileUtils.md5Sum(bout.toByteArray());
} catch (Exception e) {
throw new JadxRuntimeException("Failed to build hash for inputs", e);
}
}
}
View on GitHub (pinned to e738a26571)
Solutions
- Ensure input files are stable (not being concurrently modified/deleted) during the hash call.
- Pre-validate that all expanded input files exist: inputFiles.forEach(p -> { if (!Files.exists(p)) throw ... }).
- Filter out broken symlinks before hashing: Files.exists(path) and !Files.isSymbolicLink(path) or resolve links first.
- Copy inputs to a stable local directory before hashing in CI.
Example fix
// before
String hash = FileUtils.buildInputsHash(inputs);
// after — pre-validate existence
List<Path> expanded = FileUtils.expandDirs(inputs);
for (Path p : expanded) {
if (!Files.exists(p)) throw new IllegalStateException("input vanished: " + p);
}
String hash = FileUtils.buildInputsHash(inputs); Defensive patterns
Strategy: validation
Validate before calling
public static boolean allInputsExist(List<Path> inputs) {
for (Path p : FileUtils.expandDirs(inputs)) {
if (!Files.exists(p)) return false;
}
return true;
} Try / catch
try {
String hash = FileUtils.buildInputsHash(inputs);
} catch (JadxRuntimeException e) {
Throwable cause = e.getCause();
if (cause instanceof NoSuchFileException) {
LOG.warn("input file vanished during hashing: {}", cause.getMessage());
}
throw e;
} Prevention
- Ensure input files are stable (not concurrently modified/deleted) during hashing.
- Pre-validate that all expanded input files exist.
- Copy inputs to a stable local directory before hashing in concurrent CI.
When it happens
Trigger: Calling buildInputsHash while input files are being modified or deleted concurrently (TOCTOU race). An input path that is a broken symlink. A directory in the input list that becomes unreadable during expansion. Files on a network share that disconnects mid-hash.
Common situations: CI pipelines that clean up build artifacts while jadx is still hashing. Concurrent decompilation processes sharing the same input directory. Network-mounted input that disconnects. Broken symlinks in the input tree pointing to removed targets.
Related errors
- Failed to read res-map file
- Failed to write res-map file
- Failed to list files in directory: ${dir}
- Failed to build hash
- Config file extension should be '.json'
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/5352ffc9b6e5ed5a.
Report an issue: GitHub.