Check the actual URL first

Right-click the broken image, open it in a new tab, and look at what the browser says. That one step usually answers it.

404 — the path is wrong. See below.

403 — the file exists but permissions deny it. Check file permissions, or the bucket's access policy.

It loads fine on its own — the problem isn't the image, it's how the page references it. Check for a mixed-content block or a hotlinking restriction.

Path problems, ranked

Case sensitivity. Photo.JPG versus photo.jpg. Works on your Mac, 404s on the Linux server. The most common cause by a distance.

Relative versus absolute. images/cat.jpg resolves differently depending on the URL of the page. /images/cat.jpg is stable from any page.

The file was never deployed. Gitignored, in a build folder, or excluded by your host's config.

A build step that moves things. Your source path and your output path differ.

Mixed content

Your page is HTTPS and the image URL is HTTP. Browsers block it silently and log to the console. Fix the URL — don't disable the protection.

image-debug.txt
Images broken in production, fine locally. Opening the image URL
directly gives: <404 / 403 / it loads / mixed content warning>

My markup: <paste an img tag>
My file structure: <paste the relevant folders>
Host: <host>

Tell me which of case sensitivity, relative paths, missing deployment,
or a build path change explains this, and how I verify it.

While you're in there

Set explicit width and height so the layout doesn't jump as images load. Add real alt text. Add loading="lazy" below the fold. And check the file sizes — an unresized phone photo is several megabytes and is very likely the slowest thing on your page.

A visible broken-image icon means the browser tried and failed. No icon at all usually means your markup never rendered the tag.