spring-projects/spring-boot · error · IllegalStateException

A jar or war file is required for building image

Error message

A jar or war file is required for building image

What it means

IllegalStateException thrown by BuildImageMojo.getArchiveFile when no packaged archive can be located. The plugin first looks for target/<finalName>[<classifier>].<ext> in sourceDirectory, then falls back to the resolved source artifact's file. If neither exists, building a container image is impossible because the image tar needs an actual jar/war to embed.

Solutions

  1. Bind or run the goal as part of the package phase: `mvn package spring-boot:build-image`.
  2. Confirm the configured <classifier> (if any) matches an artifact actually produced by the build.
  3. Verify <finalName> and <sourceDirectory> so getTargetFile resolves to the real archive.
  4. Ensure the package goal (jar/war packaging) is not skipped and runs in the same lifecycle.

Example fix

// before: mvn spring-boot:build-image
// after:  mvn clean package spring-boot:build-image
Defensive patterns

Strategy: validation

Validate before calling

// Pre-build check: an archive must exist before build-image:
String ext = "jar".equals(project.getPackaging()) ? "jar" : "war";
File archive = new File(sourceDirectory, finalName + (classifier == null ? "" : "-" + classifier) + "." + ext);
if (!archive.exists()) {
    throw new IllegalStateException("Run `mvn package` before build-image; missing " + archive);
}

Try / catch

try {
    // invoke build-image
} catch (IllegalStateException ex) {
    if ("A jar or war file is required for building image".equals(ex.getMessage())) {
        // run package first, then retry
    }
    throw ex;
}

Prevention

When it happens

Trigger: Invoking spring-boot:build-image before the package phase produced an archive; classifier mismatch so getTargetFile returns a non-existent file and getSourceArtifact(classifier).getFile() is also null; package ran in a forked lifecycle leaving no file at the expected path.

Common situations: Calling build-image directly without `mvn package spring-boot:build-image`; using a <classifier> that doesn't correspond to any produced artifact; repackaging skipped; outputDirectory/finalName customized so the plugin looks in the wrong place; CI step ordering omits package.

Related errors


AI-assisted analysis of spring-projects/spring-boot@270dfe353f (2026-08-11). Data as JSON: /api/errors/c4630792c581be80. Report an issue: GitHub.

Appendix: source

Thrown at build-plugin/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java:325

			image.setImagePlatform(this.imagePlatform);
		}
		return customize(image.getBuildRequest(this.project.getArtifact(), content));
	}

	private TarArchive getApplicationContent(Owner owner, Libraries libraries, ImagePackager imagePackager) {
		ImagePackager packager = getConfiguredPackager(() -> imagePackager);
		return new PackagedTarArchive(owner, libraries, packager);
	}

	private File getArchiveFile() {
		// We can't use 'project.getArtifact().getFile()' because package can be done in a
		// forked lifecycle and will be null
		File archiveFile = getTargetFile(this.finalName, this.classifier, this.sourceDirectory);
		if (!archiveFile.exists()) {
			archiveFile = getSourceArtifact(this.classifier).getFile();
		}
		if (!archiveFile.exists()) {
			throw new IllegalStateException("A jar or war file is required for building image");
		}
		return archiveFile;
	}

	/**
	 * Return the {@link File} to use to back up the original source.
	 * @return the file to use to back up the original source
	 */
	private @Nullable File getBackupFile() {
		// We can't use 'project.getAttachedArtifacts()' because package can be done in a
		// forked lifecycle and will be null
		if (this.classifier != null) {
			File backupFile = getTargetFile(this.finalName, null, this.sourceDirectory);
			if (backupFile.exists()) {
				return backupFile;
			}
			Artifact source = getSourceArtifact(null);
			if (!this.classifier.equals(source.getClassifier())) {

View on GitHub (pinned to 270dfe353f)