theonedev/onedev · error · ExplicitException

Code read permission is required to import build spec (impor

Error message

Code read permission is required to import build spec (import project: {0}, import revision: {1})

What it means

Import.getBuildSpec requires the importing subject (job token subject or login user) to have ReadCode permission on the imported project. If neither the token subject nor the login user is permitted, it throws ExplicitException 'Code read permission is required to import build spec (import project: X, import revision: Y)'.

Source

Thrown at server-core/src/main/java/io/onedev/server/buildspec/Import.java:170

	public BuildSpec getBuildSpec() {
		if (buildSpec == null) {
			Project project = getProject();

			Subject subject;
			try {
				subject = JobAuthorizationContext.get().getSubject(getAccessTokenSecret());
			} catch (ExplicitException e) {
				var errorMessage = MessageFormat.format(
						_T("Unable to import build spec (import project: {0}, import revision: {1}): {2}"),
						projectPath, revision, e.getMessage());
				throw new ExplicitException(errorMessage);
			}
			if (!subject.isPermitted(new ProjectPermission(project, new ReadCode())) 
					&& !project.isPermittedByLoginUser(new ReadCode())) {
				String errorMessage = MessageFormat.format(
						_T("Code read permission is required to import build spec (import project: {0}, import revision: {1})"), 
						projectPath, revision);
				throw new ExplicitException(errorMessage);
			}
			
			RevCommit commit = getCommit();
			try {
				buildSpec = project.getBuildSpec(commit);
			} catch (BuildSpecParseException e) {
				String errorMessage = MessageFormat.format(
						_T("Malformed build spec (import project: {0}, import revision: {1})"), 
						projectPath, revision);
				throw new ExplicitException(errorMessage);
			}
			if (buildSpec == null) {
				String errorMessage = MessageFormat.format(
						_T("Build spec not defined (import project: {0}, import revision: {1})"), 
						projectPath, revision);
				throw new ExplicitException(errorMessage);
			}
			

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant the job token's subject ReadCode permission on the imported project (Project Partners / job authorization settings)
  2. Use a job secret containing a project access token from the imported project that has code-read rights
  3. Run the importing job as a login user with ReadCode on the target project, if applicable
  4. If the import is no longer needed, remove the Import node from the build spec

Example fix

// before: job token limited to own project, import of 'other/project' fails
// after: in project 'other/project' settings, grant the job's token subject
// ProjectPermission(name='other/project', privilege=ReadCode), or supply a
// dedicated access-token secret with code-read access to that project
Defensive patterns

Strategy: try-catch

Validate before calling

// before configuring the import, confirm the token subject can read the project:
// subject.isPermitted(new ProjectPermission(project, new ReadCode()))

Try / catch

try {
    BuildSpec imported = import_.getBuildSpec();
} catch (ExplicitException e) {
    // 'Code read permission is required...' -> grant ReadCode or use a suitable token
}

Prevention

When it happens

Trigger: A job in project A imports the build spec of project B using a job authorization token whose subject lacks ProjectPermission ReadCode on B, and no login user grants it either; thrown during getBuildSpec().

Common situations: Cross-project build spec imports between projects with isolated permissions; job tokens scoped to their own project only; guest-role users or unauthenticated jobs importing restricted projects; project permissions tightened after the import was configured.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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