skylot/jadx · error · JadxRuntimeException

Failed to build local cache dir

Error message

Failed to build local cache dir

What it means

CacheManager.buildLocalCacheDir constructs a local cache path next to the project or input files. If the project has no project path AND no file paths (files.isEmpty()), there is no basis for deriving a sibling cache directory, so a JadxRuntimeException is thrown.

Source

Thrown at jadx-gui/src/main/java/jadx/gui/cache/manager/CacheManager.java:125

	}

	private Path buildCacheDir(JadxProject project) {
		String cacheDirValue = settings.getCacheDir();
		if (Objects.equals(cacheDirValue, ".")) {
			return buildLocalCacheDir(project);
		}
		Path cacheBaseDir = cacheDirValue == null ? JadxFiles.PROJECTS_CACHE_DIR : Paths.get(cacheDirValue);
		return cacheBaseDir.resolve(buildProjectUniqName(project));
	}

	private static Path buildLocalCacheDir(JadxProject project) {
		Path projectPath = project.getProjectPath();
		if (projectPath != null) {
			return projectPath.resolveSibling(projectPath.getFileName() + ".cache");
		}
		List<Path> files = project.getFilePaths();
		if (files.isEmpty()) {
			throw new JadxRuntimeException("Failed to build local cache dir");
		}
		Path path = files.stream()
				.filter(p -> !p.getFileName().toString().endsWith(".jadx.kts"))
				.findFirst()
				.orElseGet(() -> files.get(0));
		String name = CommonFileUtils.removeFileExtension(path.getFileName().toString());
		return path.resolveSibling(name + ".jadx.cache");
	}

	private Path verifyEntry(JadxProject project, Path cacheDir) {
		boolean cacheExists = Files.exists(cacheDir);
		String key = projectToKey(project);
		CacheEntry entry = cacheMap.get(key);
		if (entry == null) {
			Path newCacheDir = cacheExists ? cacheDir : buildCacheDir(project);
			addEntry(key, newCacheDir);
			return newCacheDir;
		}

View on GitHub (pinned to e738a26571)

Solutions

  1. Ensure at least one input file is added to the project before invoking cache operations
  2. Set a project path via project.save() before cache initialization
  3. Add input files via project.addFile(path) or equivalent API before triggering cache build
  4. Initialize the project from a valid saved state rather than an empty object

Example fix

// Before any cache operation, ensure the project has inputs:
JadxProject project = new JadxProject();
project.addFile(Path.of("app.apk")); // ensure non-empty file list
project.setProjectPath(Path.of("app.jadx.kts")); // or set a project path
// Now cache operations will succeed.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure project has inputs before cache operations
if (project.getFilePaths().isEmpty() && project.getProjectPath() == null) {
    throw new IllegalStateException("Add input files before cache operations");
}

Type guard

boolean hasInputs = !project.getFilePaths().isEmpty() || project.getProjectPath() != null;
if (hasInputs) { /* safe to build cache dir */ }

Try / catch

try {
    cacheManager.getLocalCacheDir(project);
} catch (JadxRuntimeException e) {
    if (e.getMessage().contains("Failed to build local cache dir")) {
        LOG.error("Project has no input files — cannot build cache", e);
        // add inputs and retry
    }
}

Prevention

When it happens

Trigger: buildLocalCacheDir checks projectPath first (uses it if present), then falls back to project.getFilePaths(). If the file list is empty — meaning the project was created with no inputs and no saved path — the method cannot determine where to place the cache and throws.

Common situations: Programmatically creating a JadxProject without adding any input files or saving a project path. A corrupted or newly-initialized project state where file paths were cleared. Calling cache operations before loading any inputs.

Related errors


AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14). Data as JSON: /api/errors/8770b77bd763f94e. Report an issue: GitHub.