spring-projects/spring-ai · error · UnsupportedOperationException

This is a utility class and cannot be instantiated

Error message

This is a utility class and cannot be instantiated

What it means

AudioPlayer is a final utility class whose private constructor deliberately throws UnsupportedOperationException to prevent instantiation. The library throws this if any code attempts to construct an AudioPlayer instance; the class is meant to be used only via its static methods (e.g. play(...)).

Source

Thrown at spring-ai-test/src/main/java/org/springframework/ai/utils/AudioPlayer.java:35

package org.springframework.ai.utils;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

/**
 * @author Christian Tzolov
 * @since 1.0.0
 */
public final class AudioPlayer {

	private AudioPlayer() {
		throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
	}

	public static void main(String[] args) throws Exception {
		play(new BufferedInputStream(new FileInputStream(args[0])));
	}

	public static void play(byte[] data) {
		play(new BufferedInputStream(new ByteArrayInputStream(data)));
	}

	public static void play(InputStream data) {

		try {
			try (AudioInputStream audio = AudioSystem.getAudioInputStream(data); Clip clip = AudioSystem.getClip()) {
				clip.open(audio);
				clip.start();
				// wait to start
				while (!clip.isRunning()) {

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Do not instantiate: call static methods directly, e.g. AudioPlayer.play(new BufferedInputStream(new FileInputStream(file))).
  2. If coverage tools cause the error, exclude the class from instrumentation or add an inline filter for the private constructor.
  3. Use reflection with setAccessible only if absolutely required, knowing UnsupportedOperationException will still be thrown by design.

Example fix

// before
AudioPlayer player = new AudioPlayer();
// after
AudioPlayer.play(new BufferedInputStream(new FileInputStream("audio.wav")));
Defensive patterns

Strategy: type-guard

Validate before calling

// Java: never instantiate utility classes; check modifier before reflective use
if (!Modifier.isStatic(0) && !AudioPlayer.class.getSimpleName().isEmpty()) {
    Constructor<AudioPlayer> c = AudioPlayer.class.getDeclaredConstructor();
    if (c != null) throw new IllegalStateException("Do not instantiate AudioPlayer; use static play()");
}

Type guard

// Use the class only through static dispatch
static void safePlay(InputStream in) throws Exception {
    java.util.Objects.requireNonNull(in, "input stream required");
    AudioPlayer.play(in);
}

Try / catch

// Usually not caught; only needed for coverage-tool induced synthetic calls
try {
    new AudioPlayer();
} catch (UnsupportedOperationException expected) {
    // by design; switch to static usage
}

Prevention

When it happens

Trigger: Calling new AudioPlayer() anywhere in user code, or via reflection/deserialization; also hit by tools (e.g. code coverage, Jacoco) that generate synthetic constructors invoking the private constructor.

Common situations: Copy-pasted code instantiating a utility class instead of calling the static play method; test coverage tooling triggering the private constructor in instrumented builds.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/4ddc1474fa49dd19. Report an issue: GitHub.