Repository navigation
Unable to run job handler (AssetGenerateThumbnails): Error: VipsJpeg: premature end of JPEG image #24083
I have searched the existing issues, both open and closed, to make sure this is not a duplicate report.
The bugEvery midnight or when I run the "Generate thumbnails" missing job I have this error in the logs: It seems there are some corrupt files but I don't know which ones, so I can't delete them. The log level is in The OS that Immich Server is running onUbuntu Server24.04 Version of Immich Serverv2.3.1 Version of Immich Mobile Appv2.3.1 Platform with the issue
Device make and modelNo response Your docker-compose.yml contentNot necessaryYour .env contentNot necessaryReproduction stepsIt's probably some corrupted file on my side, but I can't see which files are corrupted. There should be some information about it on the logs. Relevant log outputAdditional informationNo response |
Replies: 4 comments 8 replies
|
Correct. It's indeed some corrupt file. The logs give you the asset id, indicating the specific asset that's corrupted. You can go to |
|
I had the same issue after upgrading to For @xueferLike @xuefer, my pictures reported to be corrupt. But for me, the full image data is actually intact.
Identifying files by UUID (immich running docker compose)# On the immich server
# change directory to the docker compose directory
cd ~/path/to/docker_compose/immich
# connect to postgres (you might need to enter a password if that was configured)
docker compose exec database psql -U postgres
# Change database to your immich database (in my case `immich`
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+------------+------------+-----------------------
immich | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres +
| | | | | postgres=CTc/postgres
(4 rows)
postgres=# \c immich
You are now connected to database "immich" as user "postgres".
# Run a query to find the path on disk for the UUID (replace the id below with your id)
immich=# SELECT "originalPath" FROM public.asset WHERE id = '0067c557-5dee-42e3-bf3f-734d85dfb8bf';
originalPath
-------------------------------------------------------------
/usr/src/app/external_library/2018/04/20180427_205034-1.jpgNon-fix workaround for LinuxIn my case, the image data was not actually corrupted but the files did not process (causing issues on my immich with asset generation). Here is my workaround for linux systems: Execute the command on the linux machine running immich Install required Dependencies: # install jpeginfo and imagemagick
sudo apt install jpeginfo imagemagickCreate a file (The script is written by Claude but, it performs only read operations and writes output to a log file, it will make a recursive scan of your directories for #!/usr/bin/env bash
#
# check-jpeg-truncation.sh
#
# Recursively scan a directory for corrupt / truncated JPEGs (including the
# "Premature end of JPEG file" case that breaks Immich / libvips thumbnailing)
# and write the list of bad files to a log.
#
# Uses `jpeginfo -c`, which fully decodes the entropy-coded scan data. Unlike a
# plain header check, this actually catches truncation.
#
# Usage:
# ./check-jpeg-truncation.sh [-j JOBS] [-o LOGFILE] DIRECTORY
#
# Options:
# -j JOBS Number of parallel decode jobs (default: 4)
# -o LOGFILE Output log path (default: broken_jpegs_<timestamp>.log)
# -h Show this help
#
# Log format: one bad file per line, "<path>\t<reason>"
set -euo pipefail
JOBS=4
LOGFILE="broken_jpegs_$(date +%Y%m%d_%H%M%S).log"
usage() {
cat >&2 <<'EOF'
Usage: check-jpeg-truncation.sh [-j JOBS] [-o LOGFILE] DIRECTORY
-j JOBS Number of parallel decode jobs (default: 4)
-o LOGFILE Output log path (default: broken_jpegs_<timestamp>.log)
-h Show this help
Scans DIRECTORY recursively for truncated/corrupt JPEGs and logs them.
EOF
exit "${1:-0}"
}
while getopts ":j:o:h" opt; do
case "$opt" in
j) JOBS=$OPTARG ;;
o) LOGFILE=$OPTARG ;;
h) usage 0 ;;
:)
echo "Error: -$OPTARG requires an argument" >&2
usage 1
;;
\?)
echo "Error: unknown option -$OPTARG" >&2
usage 1
;;
esac
done
shift $((OPTIND - 1))
DIR=${1:-}
[[ -z "$DIR" ]] && {
echo "Error: no directory given" >&2
usage 1
}
[[ ! -d "$DIR" ]] && {
echo "Error: '$DIR' is not a directory" >&2
exit 1
}
if ! command -v jpeginfo >/dev/null 2>&1; then
echo "Error: jpeginfo not found. Install it first" >&2
echo " Debian/Ubuntu: apt install jpeginfo" >&2
echo " macOS: brew install jpeginfo" >&2
exit 1
fi
# Decode one file; if jpeginfo reports a WARNING or ERROR, print "<path>\t<reason>".
# This catches "Premature end of JPEG file" as well as other corruption.
check_one() {
local f=$1 out reason
out=$(jpeginfo -c -- "$f" 2>&1) || true
reason=$(printf '%s\n' "$out" | grep -oiE '(WARNING|ERROR).*' | head -n1 || true)
if [[ -n "$reason" ]]; then
printf '"%s"\t%s\n' "$f" "$reason"
fi
}
export -f check_one
echo "Scanning '$DIR' with $JOBS parallel jobs..." >&2
total=$(find "$DIR" -type f \( -iname '*.jpg' -o -iname '*.jpeg' \) | wc -l | tr -d ' ')
echo "Found $total JPEG file(s) to check." >&2
# Run the decode in parallel. Bad files are streamed to the log (via tee) and to screen.
# Filenames are passed as "$0" to the inner shell so spaces/quotes/leading-dashes are safe.
find "$DIR" -type f \( -iname '*.jpg' -o -iname '*.jpeg' \) -print0 |
xargs -0 -P "$JOBS" -n1 bash -c 'check_one "$0"' |
tee "$LOGFILE"
bad=$(wc -l <"$LOGFILE" | tr -d ' ')
echo >&2
echo "Done. $bad of $total file(s) broken." >&2
echo "Log written to: $LOGFILE" >&2Make the file executable: chmod +x ~/.local/bin/premature_end_of_file_jpeg_scan.shExecute the script: After the script has completed, it will have created a file (by default broken_jpegs_.log) with content like this: Run the command below which will use imagemagick convert and create a new copy of the files (suffixed with # run this first to confirm it correctly lists your files
cat broken_jpegs_20260620_083101.log | cut -f 1 -d$'\t'
# "fix" files with convert
cat broken_jpegs_20260620_083101.log | cut -f 1 -d$'\t' | xargs -I% convert "%" "%_fixed"Manually check the files suffixed with Replace the corrupted files by the "fixed" files cat broken_jpegs_20260620_083101.log | cut -f 1 -d$'\t' | xargs -I% mv"%_fixed" "%"This should at least unblock immich asset generation but it unfortunately can't fix what is borken without restoring from backup |
|
thank you for commenting the problem picture of mine, and the workaround you provide looks promising |

Correct. It's indeed some corrupt file. The logs give you the asset id, indicating the specific asset that's corrupted. You can go to
/photos/<id>to view the asset in web