theonedev/onedev · critical · ExplicitException
Storage directory not found for project id
Error message
Storage directory not found for project id %s
What it means
OneDev throws this ExplicitException when a project's storage directory on disk does not exist. DefaultProjectService.getSubDir resolves the project's storage root; if the directory is missing (project storage never created, deleted, or on an unavailable volume) and createIfNotExist was not used for the root, the lookup fails with this error.
Solutions
- Verify the project storage directory exists under OneDev's site storage (server-core storage layout) and restore it from backup if missing.
- Check that the storage volume/disk is mounted and OneDev's storage path configuration is correct.
- If the project data is unrecoverable, delete the broken project and re-create/clone it so storage is re-initialized.
- Restart the server after fixing mounts/paths so cached state refreshes.
Example fix
// before
File gitDir = projectService.getGitDir(projectId); // throws if storage missing
// after: check storage presence first
if (!projectService.getSubDir(projectId, "", false).exists()) {
throw new IllegalStateException("Project storage missing; restore from backup for id " + projectId);
}
File gitDir = projectService.getGitDir(projectId); Defensive patterns
Strategy: validation
Validate before calling
// Verify project storage root exists before resolving sub-directories
File storageRoot = new File(storageManager.getProjectsDir(), String.valueOf(projectId));
if (!storageRoot.isDirectory()) {
throw new IllegalStateException("Project storage missing on disk for id " + projectId);
}
File gitDir = projectService.getGitDir(projectId); Type guard
function storageExists(projectService, projectId) {
try {
return projectService.getSubDir(projectId, "", false).isDirectory();
} catch (ExplicitException e) {
return false;
}
} Try / catch
try {
File gitDir = projectService.getGitDir(projectId);
} catch (ExplicitException e) {
logger.error("Project storage missing: {}", e.getMessage());
// restore from backup or re-initialize the project
} Prevention
- Back up OneDev's site/storage directory before migrations
- Monitor storage volume mounts and disk health
- Never manually delete project folders; use the product's project-delete API
- After server moves, verify each project's storage directory is present before serving traffic
When it happens
Trigger: Calling ProjectService.getSubDir(projectId, subdirPath, false) or dependent methods like getGitDir when the project's storage directory is absent on the server's file system.
Common situations: Project storage folder manually deleted or lost (disk failure, wrong volume mount); migrating servers without copying the site/storage directory; project row exists in the database but its files were never initialized (corrupted state); permission or mount changes making the path invisible.
Related errors
- Storage not found for project
- Access denied
- Active server not found for project id
- Blob not found
- Import target already exists. You need to have project…
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/fcea421c1a81d8a0.
Report an issue: GitHub.
Appendix: source
Thrown at server-core/src/main/java/io/onedev/server/service/impl/DefaultProjectService.java:1775
public File getProjectDir(Long projectId) {
return new File(getProjectsDir(), String.valueOf(projectId));
}
@Override
public File getSubDir(Long projectId, String subdirPath) {
return getSubDir(projectId, subdirPath, true);
}
@Override
public File getSubDir(Long projectId, String subdirPath, boolean createIfNotExist) {
File projectDir = getProjectDir(projectId);
if (projectDir.exists()) {
File subDir = new File(projectDir, subdirPath);
if (createIfNotExist)
FileUtils.createDir(subDir);
return subDir;
} else {
throw new ExplicitException("Storage directory not found for project id " + projectId);
}
}
@Override
public File getGitDir(Long projectId) {
return getSubDir(projectId, "git");
}
@Override
public File getInfoDir(Long projectId) {
return getSubDir(projectId, "info");
}
@Override
public File getIndexDir(Long projectId) {
return getSubDir(projectId, "index");
}
View on GitHub (pinned to d44925c47c)