wmjordan/PDFPatcher · error · ExifLibException

File is not a valid JPEG

Error message

File is not a valid JPEG

What it means

JpgHelper.Initialize throws ExifLibException('File is not a valid JPEG') when the first two bytes of the stream are not the JPEG SOI marker 0xFFD8. This is the entry-point validation that the supplied stream is actually a JPEG before attempting Exif parsing.

Source

Thrown at App/Processor/Imaging/JpgHelper.cs:142

			}

			private void Initialize() {
				if (_isInitialized)
					return;

				_isInitialized = true;

				// JPEG encoding uses big endian (i.e. Motorola) byte aligns. The TIFF encoding
				// found later in the document will specify the byte aligns used for the
				// rest of the document.
				_isLittleEndian = false;

				// Open the file in a stream            
				_reader = new BinaryReader(_stream, System.Text.Encoding.UTF8);

				// Make sure the file's a JPEG.
				if (ReadUShort() != 0xFFD8)
					throw new ExifLibException("File is not a valid JPEG");

				// Scan to the start of the Exif content
				ReadToExifStart();

				// Create an index of all Exif tags found within the document
				CreateTagIndex();
			}

			#region TIFF methods

			/// <summary>
			/// Returns the length (in bytes) per component of the specified TIFF data type
			/// </summary>
			/// <returns></returns>
			private static byte GetTIFFFieldLength(ushort tiffDataType) {
				return tiffDataType switch {
					1 or 2 or 7 or 6 => 1,
					3 or 8 => 2,

View on GitHub (pinned to 4782bbd9ad)

Solutions

  1. Verify the file type (by magic bytes / extension) before handing the stream to ExifReader.
  2. Ensure the stream position is at 0 before construction.
  3. For extracted PDF images, check the image filter/mime type to confirm it is DCTDecode (JPEG) before Exif parsing.
  4. Handle ExifLibException gracefully and skip Exif extraction for non-JPEG formats.

Example fix

// before
var reader = new ExifReader(stream);

// after
if (!IsJpeg(stream)) {
  return; // skip Exif for non-JPEG
}
stream.Position = 0;
var reader = new ExifReader(stream);

static bool IsJpeg(Stream s) {
  long p = s.Position; s.Position = 0;
  int b0 = s.ReadByte(), b1 = s.ReadByte();
  s.Position = p;
  return b0 == 0xFF && b1 == 0xD8;
}
Defensive patterns

Strategy: validation

Validate before calling

long pos = stream.Position; stream.Position = 0;
int b0 = stream.ReadByte(), b1 = stream.ReadByte();
stream.Position = pos;
if (b0 != 0xFF || b1 != 0xD8) return; // not a JPEG

Type guard

static bool IsJpeg(Stream s) {
  long p = s.Position; s.Position = 0;
  int b0 = s.ReadByte(), b1 = s.ReadByte(); s.Position = p;
  return b0 == 0xFF && b1 == 0xD8;
}

Try / catch

try { var r = new ExifReader(stream); }
catch (ExifLibException) { /* not a JPEG; skip Exif */ }

Prevention

When it happens

Trigger: Constructing the ExifReader (which lazily calls Initialize) with a stream whose first two bytes are not 0xFF 0xD8 — e.g. a PNG, GIF, TIFF, PDF, or truncated/corrupt file passed where a JPEG was expected.

Common situations: Passing a non-JPEG image stream to the Exif reader; a file with the wrong extension; a corrupted or zero-byte JPEG; a stream whose position is not at the start; mistakenly feeding a PDF object stream that isn't a JPEG.

Related errors


AI-assisted analysis of wmjordan/PDFPatcher@4782bbd9ad (2026-08-13). Data as JSON: /api/errors/672d41e64520f203. Report an issue: GitHub.