Sharp: Error: Input file is missing or of an unsupported image format on some requests

Created on 9 Mar 2019  路  4Comments  路  Source: lovell/sharp

Hello,
This code for image upload and compression works in most cases but some requests fail ((Number of fails increase in load testing) with error: 'Error: Input file is missing or of an unsupported image format'

I checked the path whenever this error appears. The file really exists and is usable. Also this error does not appear for all requests. The exception occurs when I give the temp file path (saved to disk via streams to reduce memory footprint) to sharp.

'use strict';

const fs = require('fs');
const fsx = require('fs-extra');
const path = require('path');
const sharp = require('sharp');
const Config = require('../config/image');
const Rand = require('../utils/random');
const TAG = '\services\image';
function readImageStream(buffer, owner, tempFileName){
    const tempFilepath = Config.UPLOAD_PATH+'tmp\\'+owner+'\\'+tempFileName;
    return new Promise(function(resolve, reject){
        //const readStream = fs.createReadStream(buffer);
        const readStream = buffer;
        const writeStream = fs.createWriteStream(tempFilepath);
        let output;
        readStream.on('data', function(chunk){
            writeStream.write(chunk, {flags: 'a', encoding:null, mode:0o666});
        });
        readStream.on('end', function(){
            const path = writeStream.path;
            writeStream.end();
            resolve(path);
        });
        readStream.on('error', function(err){
            console.log("Error in reading image stream " + TAG, err);
            reject(err);
        });
    });
}

function checkImageDimensions(owner, filename){
    const path = Config.UPLOAD_PATH + "tmp\\"+ owner + "\\" + filename;
    return new Promise(function(resolve, reject){

        sharp(path)
            .metadata()
            .then(function(info){
                if(info.width < 100 || info.height <100 || 
                  (info.width / info.height < 0.5) ||
                  (info.height / info.width < 0.5)){
                        reject('Bad image size');
        }
        else{
            resolve();
        }
        })
        .catch(function(err){
            console.log("Error in image size check " + TAG, err);
            reject(err);
        })
    }); 
}

exports.Save = async function(owner, buffer){
    const tempDir = Config.UPLOAD_PATH+"tmp\\"+owner;
    const tempFileName1 = Rand.UUID() + Config.EXTENSION; //Creates UUID for filename
    const tempFileName2 = Rand.UUID() + Config.EXTENSION;
    const tempPath = tempDir + "\\"+tempFileName1;
    const ensureDirExists = await fsx.ensureDir(Config.UPLOAD_PATH+ "tmp\\"+owner);
    //await checkMaxTempSize(owner);
    await readImageStream(buffer, owner, tempFileName1);
    await checkImageDimensions(owner, tempFileName1);
    try{
        await sharp(tempPath)
                    .resize(800, 494, {
                                        kernel: sharp.kernel.nearest,
                                        fit: 'contain',
                                        background: { r: 255, g: 255, b: 255}
                                    }).toFile(Config.UPLOAD_PATH+ "tmp\\"+owner+ "\\" + tempFileName2, {quality:80});
                return {
                        filename: tempFileName2
                };
    }
    catch(err){
        console.log("Error in image compression " + TAG, err);
        return err;
    }
} 
question

All 4 comments

Hi, there's a race condition in the following section of your code, unrelated to sharp:

readStream.on('end', function(){
    const path = writeStream.path;
    writeStream.end();
    resolve(path);
});

The call to writeStream.end() is not synchronous so resolve could occur before writeStream has finished writing to and closing the underlying file descriptor.

Instead listen for the close event on writeStream before resolving.

Hi, I've experienced the same issue. In some cases it works properly, but it often happens to get the error mentioned above. I've tried to check the details of a "working" image and a "non-working" image. The only difference is the file-type. For not working images we have:

File Type: JPEG image data, JFIF standard 1.02

My current settings to resize is:

sharp(filePath) .withMetadata() .resize(200, 200, { withoutEnlargement: true }) .png() .toFile(newFilePath);

I am using the latest version, but also tried an earlier one (0.20.5). The result was the same.

I hope we can figure this out, and thanks in advance.

@gergo0720 Please open a new issue with a standalone code sample and example input image that consistently fails.

Thanks a million @lovell I spent almost a month on solving the issue and tried many possibilities, finally I suspected about internal streams that sharp use to open files. It now works like a charm. God bless you man!

Was this page helpful?
0 / 5 - 0 ratings