theonedev/onedev · error · ExplicitException

Artifact path has to be specified

Error message

Artifact path has to be specified

What it means

ArtifactResource requires an artifact file path. After filtering empty path segments, if no segments remain it throws ExplicitException 'Artifact path has to be specified', since the resource is meant to download a specific artifact file, not a listing.

Source

Thrown at server-core/src/main/java/io/onedev/server/web/resource/ArtifactResource.java:57

	@Override
	protected ResourceResponse newResourceResponse(Attributes attributes) {
		PageParameters params = attributes.getParameters();

		Long projectId = params.get(PARAM_PROJECT).toLong();
		Long buildNumber = params.get(PARAM_BUILD).toLong();
		
		List<String> pathSegments = new ArrayList<>();

		for (int i = 0; i < params.getIndexedCount(); i++) {
			String pathSegment = params.get(i).toString();
			if (pathSegment.contains(".."))
				throw new ExplicitException("Invalid request path");
			if (pathSegment.length() != 0)
				pathSegments.add(pathSegment);
		}
		
		if (pathSegments.isEmpty())
			throw new ExplicitException("Artifact path has to be specified");
		
		String artifactPath = Joiner.on("/").join(pathSegments);
		
		FileInfo fileInfo = null;
		if (!SecurityUtils.isSystem()) {
			Project project = OneDev.getInstance(ProjectService.class).load(projectId);
			
			Build build = OneDev.getInstance(BuildService.class).find(project, buildNumber);

			if (build == null) {
				String message = String.format("Unable to find build (project: %s, build number: %d)", 
						project.getPath(), buildNumber);
				throw new EntityNotFoundException(message);
			}
			
			if (!SecurityUtils.canAccessProject(build.getProject()))
				throw new UnauthorizedException();
			

View on GitHub (pinned to d44925c47c)

Solutions

  1. Append the artifact file path to the URL, e.g. .../artifact/<project>/<build>/target/app.jar
  2. Verify the variable holding the artifact path is non-empty in your script/CI step
  3. Browse the build's artifacts in the OneDev UI and copy the exact link to confirm the path

Example fix

// before
GET /~resources/artifact/1/5
// after
GET /~resources/artifact/1/5/target/app.jar
Defensive patterns

Strategy: validation

Validate before calling

if (!artifactPath || artifactPath.split('/').filter(Boolean).length === 0) throw new Error('artifact path is required, e.g. target/app.jar');
const url = `~/.artifact/${projectId}/${buildNumber}/${artifactPath}`;

Type guard

function hasArtifactPath(p) { return typeof p === 'string' && p.split('/').some(s => s.length > 0); }

Prevention

When it happens

Trigger: Calling the artifact resource with project/build parameters but no indexed path segments (empty trailing path), or a path consisting only of empty segments like double slashes.

Common situations: URL template with an unfilled path variable; URL ending in a separator so the path portion is dropped; scripts that pass an empty artifact path variable.

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