theonedev/onedev · error · ExplicitException

Project not specified

Error message

Project not specified

What it means

GitLfsFilter extracts the project path from an LFS request pathInfo by stripping the trailing '.git/' (and LFS-specific '.git.git/') segments; if the result is blank it throws this ExplicitException. Like GitFilter, this indicates a malformed LFS URL with no project path rather than a missing project.

Source

Thrown at server-core/src/main/java/io/onedev/server/git/GitLfsFilter.java:158

					return true;
			}
			return false;
		} else {
			return true;
		}
	}

	private String getObjectUrl(HttpServletRequest request, String projectPath, 
			String objectId, boolean clusterAccess) {
		var serverUrl = clusterAccess ? clusterService.getServerUrl(clusterService.getLocalServerAddress()) : settingService.getSystemSetting().getServerUrl();
		return String.format("%s/%s.git/lfs/objects/%s?lfs-objects=true", 
				StringUtils.stripEnd(serverUrl, "/\\"), projectPath, objectId);
	}

	private String getProjectPath(String pathInfo) {
		String projectPath = substringBeforeLast(substringBeforeLast(pathInfo, ".git.git/"), ".git/");
		if (StringUtils.isBlank(projectPath))
			throw new ExplicitException("Project not specified");
		return decodeFullRepoNameAsPath(projectPath);
	}

	private void reportProjectNotFoundOrInaccessible(HttpServletResponse response, String projectPath) {
		if (SecurityUtils.getUser() != null) {
			sendBatchError(response, SC_NOT_FOUND, "Project not found or inaccessible: " + projectPath);
		} else {
			response.addHeader("LFS-Authenticate", "Basic realm=\"OneDev\"");
			sendBatchError(response, SC_UNAUTHORIZED, "Authentication required");
		}
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest httpRequest = (HttpServletRequest) request;
		HttpServletResponse httpResponse = (HttpServletResponse) response;
		String uri = httpRequest.getRequestURI();

View on GitHub (pinned to d44925c47c)

Solutions

  1. Fix the LFS endpoint so it includes the repository path, e.g. lfs.url = https://server/myproject.git/info/lfs
  2. Remove a stale/incorrect .lfsconfig from the repo or set it correctly
  3. Verify reverse-proxy rules preserve the full path for /info/lfs requests
  4. Run GIT_TRACE=1 git lfs env / git lfs logs to inspect the URL being used

Example fix

// .lfsconfig before
[lfs]
	url = https://onedev.example.com/info/lfs

// after
[lfs]
	url = https://onedev.example.com/myproject.git/info/lfs
Defensive patterns

Strategy: validation

Validate before calling

const lfsUrl = new URL(lfsEndpoint);
if (lfsUrl.pathname.replace(/\/$/, '').split('/').length < 2) {
  throw new Error('lfs.url must include the project path, e.g. https://server/myproject.git/info/lfs');
}

Prevention

When it happens

Trigger: An LFS batch/upload/download request whose pathInfo yields an empty projectPath after substringBeforeLast stripping — e.g. GET/POST to /git or a URL missing the repository segment entirely; getProjectPath is invoked from projectPath() and project() helpers for every LFS operation.

Common situations: Misconfigured git-lfs lfs.url endpoint without project path; broken .lfsconfig pointing at the server root; proxy rewrite removing the repo segment; hand-crafted curl against the LFS API with no repo path.

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