theonedev/onedev · error · ExplicitException

Project not specified

Error message

Project not specified

What it means

SshCommand.start resolves the project path from the SSH command (stripping a single trailing '.git') via projectService.findFacadeByPath. If after this the project path is blank it throws ExplicitException("Project not specified") — the SSH command did not include a parseable project path, so nothing can be executed.

Source

Thrown at server-core/src/main/java/io/onedev/server/git/SshCommand.java:103

		boolean upload = commandString.startsWith(RemoteConfig.DEFAULT_UPLOAD_PACK);
		String protocol = environments.get("GIT_PROTOCOL");
		
		SshAuthenticator authenticator = OneDev.getInstance(SshAuthenticator.class);
		ThreadContext.bind(asSubject(asPrincipals(asUserPrincipal(authenticator.getPublicKeyOwnerId(session)))));
		
		boolean clusterAccess = SecurityUtils.isSystem();		
		
		ProjectService projectService = OneDev.getInstance(ProjectService.class);

		var tempStr = StringUtils.substringAfter(commandString, "'/");   
		var projectPath = decodeFullRepoNameAsPath(substringBefore(tempStr, "'"));
		var projectFacade = projectService.findFacadeByPath(projectPath);
		if (projectFacade == null && projectPath.endsWith(".git")) {
			projectPath = StringUtils.substringBeforeLast(projectPath, ".");
			projectFacade = projectService.findFacadeByPath(projectPath);				
		}
		if (StringUtils.isBlank(projectPath))
			throw new ExplicitException("Project not specified");
        if (projectFacade == null) {
			reportProjectNotFoundOrInaccessible(projectPath);
			return;
        } 
		
		ClusterService clusterService = OneDev.getInstance(ClusterService.class);
		
		String activeServerAddress = projectService.getActiveServer(projectFacade.getId(), true);
		if (clusterAccess || activeServerAddress.equals(clusterService.getLocalServerAddress())) {
	        File gitDir = OneDev.getInstance(ProjectService.class).getGitDir(projectFacade.getId());
			String principal = (String) SecurityUtils.getSubject().getPrincipal();
	        Map<String, String> hookEnvs = HookUtils.getReceiveHookEnvs(projectFacade.getId(), principal);

	        if (!clusterAccess) {
		        SessionService sessionService = OneDev.getInstance(SessionService.class);
		        sessionService.openSession(); 
		        try {
		        	Project project = projectService.load(projectFacade.getId());

View on GitHub (pinned to d44925c47c)

Solutions

  1. Include the project path in the SSH command: ssh user@server git-upload-pack '<project-path>.git'
  2. Fix the remote URL (git remote set-url) so the repository path is present and correct
  3. Check the path/case and user's access if the facade lookup also fails (project reported not found/inaccessible)

Example fix

# before
git remote add origin ssh://user@server           # no project path
# after
git remote set-url origin ssh://user@server/myproject.git
Defensive patterns

Strategy: validation

Validate before calling

// check command shape before invoking ssh
String repoArg = /* parsed from ssh command */;
if (repoArg == null || repoArg.replace(".git", "").isBlank())
  throw new IllegalArgumentException("SSH command missing project path");

Try / catch

try {
  sshCommand.start();
} catch (ExplicitException e) {
  if ("Project not specified".equals(e.getMessage())) {
    // fix remote URL / re-run with repository argument
  }
}

Prevention

When it happens

Trigger: An SSH command whose target cannot be parsed into a non-blank project path — e.g. 'ssh user@server git-upload-pack' with no repository argument, or an empty path component after stripping '.git'.

Common situations: Misconfigured Git remote URL missing the repository path; invoking the ssh git command manually without arguments; a client tool constructing a URL with an empty repo segment.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/dd8630fa0424742d. Report an issue: GitHub.