ENOENT reading image from content/images — storage adapter or missing file?
0 reputation · 19 Mar 2023, 14:10 UTC
0 reputation · 19 Mar 2023, 14:10 UTC
Ghost logs an ENOENT error when it tries to read an image from the content/images directory. The stack trace appears to come from the storage adapter layer (ghost-storage-adapter-base), which sits between Ghost core and either the local filesystem or an external service such as S3. The goal is to determine whether the failure means the file is genuinely absent, or whether the configured adapter cannot locate an existing file.
The exact message seems to vary by Ghost version and by the storage.active setting in the config file, and a misconfigured adapter can reportedly produce the same ENOENT even when files exist on disk. Debug logging and reproducing the request against a known-missing URL should clarify where the trace originates, but that has not been confirmed yet.
Separately, since Ghost currently delegates image resizing and optimization to the user or external services, there is an open question about whether relying on the adapter layer for any future built-in image pipeline would change how these errors surface.
ENOENT from a missing file be reliably distinguished from one caused by a misconfigured storage adapter?32775 reputation · 19 Mar 2023, 15:15 UTC
When Ghost logs ENOENT while trying to serve content/images assets, the error can originate from two places:
ENOENT when the requested file does not exist on the disk or in the configured bucket.Distinguishing between these two is straightforward once you enable adapter‑level debugging and verify the resolved path.
Start Ghost with the DEBUG environment variable set to include the storage subsystem:
DEBUG=storage* npm start
The log will contain a line similar to:
storage:stat /var/www/ghost/content/images/hero.jpg: ENOENT
The part after storage:stat shows the absolute path the adapter attempted to access.
On the host, run:
ls -l /var/www/ghost/content/images/hero.jpg
If the file is present and the command succeeds, the adapter is mis‑configured. If ls also reports ENOENT, the file truly does not exist.
Check the relevant keys in config.js (or config.production.json):
storage.active – should be "local" or the name of the S3 adapter.storage.path – relative to the contentPath and must match the directory that contains the images.endpoint, bucket, and region must point to the bucket that actually holds the images.A common pitfall is leaving storage.path set to the default images while the images are stored elsewhere, causing the adapter to look in a non‑existent subfolder.
Ghost runs under a specific user (often www-data or ghost). Ensure that user has read permission for the content/images directory and all parent directories:
sudo -u www-data ls -l /var/www/ghost/content/images
Missing read rights will also surface as ENOENT because the OS denies access.
Request an image URL that you know does not exist, e.g. /ghost/ghost-image-404.jpg. If Ghost still returns ENOENT but the log shows the correct absolute path, you can be confident the file is truly missing.
Ghost 5.x uses the ghost-storage-adapter-base package, which logs errors in the format:
ENOENT: no such file or directory, stat <path>. In Ghost 4.x the adapter prefix may be omitted, yielding just ENOENT: no such file or directory. The DEBUG=storage* flag reveals the exact adapter name (local or s3) and the underlying OS or SDK call that produced the error, making it easier to pinpoint mis‑configuration.
As of 2026, Ghost does not ship a built‑in image optimization pipeline. External services or manual resizing remain the standard approach. Any future opt‑in feature that introduces image processing would likely add new adapter steps (e.g. resize hooks), but the error surface should remain similar: the adapter will still emit ENOENT if it cannot locate the source file.
To tailor the recommendation further, could you confirm the Ghost major version you are running? Knowing whether you are on 4.x or 5.x will help determine the exact log format and any subtle differences in the adapter API.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.