theonedev/onedev · error · ExplicitException

Project not specified

Error message

Project not specified

What it means

GitFilter resolves the project from the Git URL path before serving git HTTP requests (clone/fetch/push). When the extracted project path is blank — meaning the request URL did not contain any project path at all — it throws this ExplicitException instead of attempting a lookup. It signals a malformed request rather than a missing project.

Source

Thrown at server-core/src/main/java/io/onedev/server/git/GitFilter.java:101

		this.workExecutionService = workExecutionService;
		this.sessionService = sessionService;
		this.clusterService = clusterService;
		this.codePullAuthorizationSources = codePullAuthorizationSources;
	}
	
	private String getPathInfo(HttpServletRequest request) {
		String pathInfo = request.getRequestURI().substring(request.getContextPath().length());
		return StringUtils.stripStart(pathInfo, "/");
	}
	
	private Long getProjectId(String projectPath, boolean clusterAccess, boolean upload) {
		var facade = projectService.findFacadeByPath(projectPath);
		if (facade == null && projectPath.endsWith(".git")) {
			projectPath = StringUtils.substringBeforeLast(projectPath, ".");
			facade = projectService.findFacadeByPath(projectPath);
		}
		if (StringUtils.isBlank(projectPath))
			throw new ExplicitException("Project not specified");
		if (facade == null) 
			reportProjectNotFoundOrInaccessible(projectPath);
		return facade.getId();
	}

	private void reportProjectNotFoundOrInaccessible(String projectPath) {
		if (SecurityUtils.getUser() != null)
			throw new EntityNotFoundException("Project not found or inaccessible: " + projectPath);
		else
			throw new UnauthorizedException("Authentication required");
	}

	private void doNotCache(HttpServletResponse response) {
		response.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache, max-age=0, must-revalidate");
	}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Check the git remote URL / request URL and ensure it includes the full project path, e.g. git clone https://server/myproject.git
  2. If behind a reverse proxy, verify proxy rewrite rules do not strip the project path segment
  3. Fix the CI/script variable that generates the URL so it is not empty
  4. Reproduce the request manually with curl to confirm the path segment is present

Example fix

// before
git clone https://onedev.example.com/git

// after
git clone https://onedev.example.com/git/myproject.git
Defensive patterns

Strategy: validation

Validate before calling

const projectPath = new URL(remoteUrl).pathname.replace(/^\/git\//, '').replace(/\.git$/, '');
if (!projectPath) throw new Error('Remote URL must include a project path, e.g. /git/myproject.git');

Prevention

When it happens

Trigger: Calling any git smart-HTTP endpoint (info/refs, git-upload-pack, git-receive-pack) with a pathInfo from which getProjectId cannot extract a project path, so StringUtils.isBlank(projectPath) is true. Note the blank check happens after the .git-suffix stripping, so even the original path was empty.

Common situations: Hitting the bare /git or repository root endpoint directly in a browser or curl without a project path; misconfigured reverse-proxy rewrites that drop the path segment; broken CI scripts that build the clone URL with an empty project variable; copy-pasting a URL missing the project portion (e.g. https://server/git instead of https://server/git/myproject).

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/b6b6f79fe0d5a6f7. Report an issue: GitHub.