What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Short answer: this error means the browser could not find a usable audio or video source when play() was called. It does not automatically mean that the codec is unsupported. A wrong relative path, 404 response, HTML page returned instead of an MP3, invalid file, incorrect MIME type, cross-origin restriction, or autoplay policy can lead to the same failure.
Start by catching the play() Promise, checking the exact URL in DevTools, and confirming that the response is a real media file. For the common example new Audio("../../media/KR881.mp3").play(), the path and server response are the first things to investigate.
What the exception means
HTMLMediaElement.play() is asynchronous and returns a Promise. The Promise rejects when playback cannot begin. A source-related failure commonly appears as:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallNotSupportedError: Failed to load because no supported source was found
The browser may have found no usable source because the URL was unreachable, the response was invalid, or the media could not be decoded. Chromium separates this failure from autoplay-policy failures in its media implementation. See the Chromium media-element source.
#1 Best Overall
Always handle the Promise:
const audio = new Audio("/media/KR881.mp3");
audio.play()
.then(() => console.log("Playback started"))
.catch(error => console.error(error.name, error.message));
NotAllowedError means the browser blocked playback under its autoplay policy, usually because there was no recent user interaction. That is different from NotSupportedError. AbortError generally indicates that playback was interrupted or superseded. See MDN’s play() documentation.
1. Check the URL before changing the codec
In this code:
const audio = new Audio("../../media/KR881.mp3");
audio.play();
the relative URL is resolved against the document’s base URL, not necessarily against the directory containing the JavaScript file. If the page is served from /app/, for example, ../../media/KR881.mp3 may resolve somewhere entirely different from the source-tree path you had in mind.
Print the resolved URL:
const audio = new Audio("../../media/KR881.mp3");
console.log(audio.src);
Then copy that URL into a browser tab. It should return or download the actual audio file—not a 404 page, application shell, login page, JSON response, or other HTML document.
Common path problems include:
- The file is not in the directory implied by the URL.
- The filename or extension is misspelled.
- Uppercase and lowercase letters differ. This often works on a case-insensitive development machine but fails on a case-sensitive production server.
- A leading slash was misunderstood.
/media/song.mp3means the origin root, not the folder containing the project source. - A framework’s public/static directory or bundler import convention was not followed.
- A route fallback returns
index.htmlfor an unknown media URL.
Document-relative, root-relative, and imported assets
If the directory layout is:
project/
├── index.html
└── media/
└── KR881.mp3
and index.html is in the project root, this is appropriate:
const audio = new Audio("./media/KR881.mp3");
When the file is served from the site origin’s root, this may be appropriate:
const audio = new Audio("/media/KR881.mp3");
In bundler-based projects, the asset may need to be imported:
import songUrl from "./assets/KR881.mp3";
const audio = new Audio(songUrl);
These are patterns, not universal framework rules. The generated URL shown in the browser’s Network panel is the authority.
Free tools Windows power users keep installed
One-click scans. No signup required.
2. Use the Network panel to find the real failure
- Open DevTools and select Network.
- Clear the request log.
- Click the playback button.
- Filter for
media,mp3,wav,ogg, or the filename. - Inspect the request URL, status, redirects, response headers, and response size.
- Open the request URL directly or download the response to verify its contents.
- Check the Console for CORS, mixed-content, MIME, or authentication errors.
| Network result | Likely cause |
|---|---|
| 404 | Wrong path, filename, case, or static-asset configuration. |
| 403 | Permission, authentication, or server policy. |
200 with text/html |
An error page, login page, or single-page-app fallback was returned instead of audio. |
| 200 with an empty or implausibly small body | Broken deployment or an empty asset. |
| CORS error | The cross-origin server did not provide a suitable Access-Control-Allow-Origin header. |
| Mixed-content error | An HTTPS page attempted to load media over HTTP. |
| No request appears | The handler did not run, the URL was never assigned, or another JavaScript error stopped execution. |
A 200 status alone does not prove that the media is valid. Servers frequently return an HTML fallback with status 200.
3. Run the project through a local web server
Opening an HTML file by double-clicking it gives the page a file:// URL. Simple local audio playback can work in some browsers and setups, but filesystem behavior, relative paths, modules, CORS, and security restrictions are less predictable than normal HTTP serving.
From the directory you want to expose, run:
python -m http.server 8000
Then visit http://localhost:8000/. The command serves the directory in which it was started, so run it from the directory containing your HTML file and media folder.
A local server does not repair a missing file, corrupt encoding, incorrect MIME type, or unsupported codec. It simply gives you predictable URL resolution and useful Network-panel results.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →4. Verify the MIME type and the file itself
The server should send an appropriate Content-Type, such as:
audio/mpegfor MP3audio/oggfor Ogg audioaudio/wavfor WAVaudio/mp4for supported MP4 audiovideo/mp4for MP4 videovideo/webmfor WebM video
For an MP3 source, use the conventional MIME type audio/mpeg:
<audio controls>
<source src="/media/song.mp3" type="audio/mpeg">
</audio>
audio/mp3 is commonly seen, but audio/mpeg is the conventional type. The response header from the server matters more than the filename extension.
Also confirm that the file is genuine media. An MP3 filename may contain a WAV file, an HTML error page, JSON, a partial upload, an empty output from a conversion job, or a corrupt encoding. Download the exact response and test it in a desktop media player or media-information utility. If it cannot be decoded outside the browser, JavaScript is not the cause.
5. Check format and codec support
A filename such as .mp3, .mp4, or .webm does not guarantee that the contents are valid or that a particular browser can decode them. A media resource has a container or format and an encoded audio or video codec.
Rank #3
canPlayType() provides an advisory browser hint:
const audio = document.createElement("audio");
console.log(audio.canPlayType("audio/mpeg"));
// Usually "probably", "maybe", or ""
An empty string means the browser does not think it can play that type. However, a nonempty result does not verify that the URL exists or that the file is undamaged. See MDN’s canPlayType() reference.
For alternatives, provide multiple correctly declared sources:
<audio id="player" controls>
<source src="/media/song.mp3" type="audio/mpeg">
<source src="/media/song.ogg" type="audio/ogg">
Your browser does not support HTML audio.
</audio>
If every URL is wrong, every response is invalid, or every type declaration is misleading, the browser can still report that no supported source was found. More sources are not a substitute for testing each request.
6. Call play() from a user action
For reliable interactive playback, call play() directly from a button’s click handler:
<button id="play-button" type="button">Play song</button>
const audio = new Audio("/media/KR881.mp3");
const button = document.querySelector("#play-button");
button.addEventListener("click", async () => {
try {
await audio.play();
console.log("Playing");
} catch (error) {
console.error("Could not play audio:", error.name, error.message);
}
});
An asynchronous operation before play() can lose the user-gesture context in some browsers:
button.addEventListener("click", async () => {
await someLongOperation();
await audio.play();
});
If the rejection is NotAllowedError, investigate autoplay and interaction policy. Do not diagnose it as an MP3 or path problem.
7. Retain the audio object
Keeping one Audio instance makes pause, restart, status events, and cleanup straightforward. Creating a new instance on every click can result in multiple simultaneous players and makes later control difficult, although it is not usually the direct cause of NotSupportedError.
Recommended Free Tools
const audio = new Audio("/media/song.mp3");
playButton.addEventListener("click", () => {
audio.play().catch(console.error);
});
pauseButton.addEventListener("click", () => {
audio.pause();
});
8. Play a file selected by the user
A browser cannot safely use an arbitrary path guessed from the user’s filesystem. For an <input type="file">, create a temporary object URL:
<input id="file-input" type="file" accept="audio/*">
<audio id="player" controls></audio>
const input = document.querySelector("#file-input");
const player = document.querySelector("#player");
let objectUrl;
input.addEventListener("change", () => {
const file = input.files[0];
if (!file) return;
if (objectUrl) URL.revokeObjectURL(objectUrl);
objectUrl = URL.createObjectURL(file);
player.src = objectUrl;
player.play().catch(error => {
console.error("Selected file could not be played:", error);
});
});
URL.createObjectURL() creates a temporary blob: URL. It does not upload the file or reveal an arbitrary local path. Revoke the previous URL when replacing it.
9. Diagnose media state and selected source
This version logs the source the browser selected and any available media error:
const audio = new Audio();
audio.addEventListener("error", () => {
const mediaError = audio.error;
console.error("Media error", {
code: mediaError?.code,
message: mediaError?.message,
networkState: audio.networkState,
readyState: audio.readyState,
src: audio.currentSrc || audio.src
});
});
audio.addEventListener("loadedmetadata", () => {
console.log("Metadata loaded", {
duration: audio.duration,
currentSrc: audio.currentSrc
});
});
audio.src = "/media/KR881.mp3";
document.querySelector("#play-song").addEventListener("click", async () => {
try {
await audio.play();
} catch (error) {
console.error("play() rejected:", error);
}
});
The audio.error property and MediaError code can narrow the diagnosis, but they usually cannot tell you whether the original mistake was a path, server, or deployment configuration. The Network response remains essential.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errors10. Check deployment-specific problems
CORS
Cross-origin media must satisfy the browser and the remote server’s policy. If the server does not send a suitable Access-Control-Allow-Origin header, the request may be blocked. Setting audio.crossOrigin = "anonymous" is not a universal fix: it only works when the remote server is configured accordingly, and it cannot repair a 404, invalid file, or unsupported codec.
For simple playback, configure the media host correctly. If you use the media with Web Audio, canvas, or APIs that inspect its data, CORS requirements can be stricter.
HTTPS, redirects, and authentication
- An HTTPS page cannot normally load media over insecure HTTP because of mixed-content blocking.
- A redirect may lead to a login page or another origin with different permissions.
- Signed URLs can expire before playback begins.
- Protected media may require credentials or headers that a plain media element does not send as expected.
Inspect the final URL and response, not only the original URL typed into the code.
Range requests
For longer audio and video, a server or CDN should support byte-range requests. Missing range support is more commonly associated with seeking and streaming problems than this exact exception, but it is worth checking when short files work and larger deployed files do not.
A complete robust example
<button id="play-song" type="button">Play song</button>
<button id="pause-song" type="button">Pause</button>
<p id="status" role="status">Ready</p>
<script>
const audio = new Audio("./media/KR881.mp3");
const playButton = document.querySelector("#play-song");
const pauseButton = document.querySelector("#pause-song");
const status = document.querySelector("#status");
audio.addEventListener("loadedmetadata", () => {
status.textContent = `Ready (${audio.duration.toFixed(1)} seconds)`;
});
audio.addEventListener("error", () => {
const mediaError = audio.error;
status.textContent = "The media could not be loaded.";
console.error("Media error", {
code: mediaError?.code,
message: mediaError?.message,
currentSrc: audio.currentSrc || audio.src,
networkState: audio.networkState,
readyState: audio.readyState
});
});
playButton.addEventListener("click", async () => {
try {
await audio.play();
status.textContent = "Playing";
} catch (error) {
status.textContent = `Playback failed: ${error.name}`;
console.error(error);
}
});
pauseButton.addEventListener("click", () => {
audio.pause();
status.textContent = "Paused";
});
</script>
Final troubleshooting checklist
- Catch the
play()Promise and printerror.name. - Check
audio.currentSrcand resolve the URL from the document location. - Open the exact URL directly.
- Use DevTools Network to check status, redirects, response size, and
Content-Type. - Make sure a 200 response contains media rather than HTML, JSON, or an application shell.
- Check filename case and framework static-asset conventions.
- Verify the downloaded file in another media player.
- Use
canPlayType()only as a preliminary compatibility hint. - Try a known-good format or provide multiple correctly declared sources.
- Use a local HTTP server instead of relying on
file://. - Call
play()from a user click and distinguishNotAllowedErrorfromNotSupportedError. - For remote media, check CORS, HTTPS, authentication, redirects, and range support.
The central diagnosis is simple: “no supported source” means no usable resource was available to the media element at that moment. Find out whether the failure is in the URL, response, file, codec, browser policy, or deployment configuration before changing the JavaScript.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

