theonedev/onedev · error · ExplicitException

Unable to import build spec (import project: {0}, import rev

Error message

Unable to import build spec (import project: {0}, import revision: {1}): {2}

What it means

Import.getBuildSpec loads a build spec from another project/revision on behalf of the current job subject. If creating the authorization subject from the access token fails (ExplicitException), the message is wrapped as 'Unable to import build spec (import project: X, import revision: Y): <cause>'. This indicates the import itself could not authenticate, not a permission shortfall.

Source

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

	
	@SuppressWarnings("unused")
	private static List<String> getAccessTokenSecretChoices() {
		return Project.get().getHierarchyJobSecrets()
				.stream().map(it->it.getName()).collect(Collectors.toList());
	}
	
	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);
			}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Regenerate the project access token and update the job secret used by the import
  2. Verify the job secret name referenced in accessTokenSecret actually exists and holds a valid token
  3. Check the import revision/branch still exists in the target project
  4. Confirm the import project path is spelled correctly and the project exists

Example fix

// before: token secret deleted/rotated
accessTokenSecret: old-project-token
// after
accessTokenSecret: project-token   # secret recreated with a live access token
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the job secret referenced by accessTokenSecret exists and the token is not expired
// (check in Project > Access Tokens before configuring the import)

Try / catch

try {
    BuildSpec imported = import_.getBuildSpec();
} catch (ExplicitException e) {
    // 'Unable to import build spec ...: <cause>' -> fix token/revision per cause
}

Prevention

When it happens

Trigger: A job secret/token used for the import is invalid, expired, revoked, or empty; JobAuthorizationContext.get().getSubject(accessTokenSecret) throws ExplicitException during getBuildSpec().

Common situations: Referencing another project's build spec with a job token that lacks access; rotating project access tokens without updating the job secret; typos in the secret reference so the token resolves to nothing; importing from a revision that no longer exists.

Related errors


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