aheckmann / gm

GraphicsMagick for node
http://aheckmann.github.com/gm/
6.95k stars 615 forks source link

EPIPE throw on calling gm.identify (macos Big Sur) #826

Open igal1c0de4n opened 3 years ago

igal1c0de4n commented 3 years ago

I've been using npm gm for years on macos. For a long time gm image processing worked great - until a few days/weeks ago and I can't figure out what broke it. My code:

aws.S3.getObject(bucket, key).then(imageFile => {
  const buffer = imageFile.Body
  const stream = gm(buffer).identify(...)
}

Recently it started throwing this stack:

Error: write EPIPE
    at afterWriteDispatched (internal/stream_base_commons.js:156:25)
    at writeGeneric (internal/stream_base_commons.js:147:3)
    at Socket._writeGeneric (net.js:787:11)
    at Socket._write (net.js:799:8)
    at doWrite (_stream_writable.js:403:12)
    at writeOrBuffer (_stream_writable.js:387:5)
    at Socket.Writable.write (_stream_writable.js:318:11)
    at gm._spawn (/Users/igal/work/mapme-apis/node_modules/gm/lib/command.js:253:18)
    at gm._exec (/Users/igal/work/mapme-apis/node_modules/gm/lib/command.js:190:17)
    at gm.identify (/Users/igal/work/mapme-apis/node_modules/gm/lib/getters.js:127:10)
   ....

GM/IM versions:

$ brew info graphicsmagick
graphicsmagick: stable 1.3.36 (bottled), HEAD
...
$ brew info imagemagick
imagemagick: stable 7.0.11-4 (bottled), HEAD
...
$ grep gm  package.json
    "gm": "^1.23.1",
...
- macos version: Big Sur 11.2.3 (20D91)
- My app runs in Meteor 2.1.

I've added/removed/cleaned/reinstalled graphicsmagick and imagemagick. Nothing helps.

Any advice??

igal1c0de4n commented 3 years ago

Ok, I figured out the problem. It's actually quite silly: I run meteor via webstorm with environment variables.

The "Include system environment variables" option is checked, but for some reason the default PATH variable didn't include /usr/local/bin. Since the identify symlink is located there it isn't found. After adding this directory to the PATH everything went back to working just as before.

So the real issue here is a wrong or "useless" error message.

Ideally, gm would be logging Unable to locate 'identify' in $PATH.

Instead, gm fails to run 'identify' but still feeds the buffer into the stdin of the failed process. This results in an EPIPE throw.

Looks like there's error handling in gm code:

    proc.on('error', function(err){
      if (err.code === 'ENOENT') {
        cb(new Error('Could not execute GraphicsMagick/ImageMagick: '+cmd+" this most likely means the gm/convert binaries can't be found"));
      } else {
        cb(err);
      }
    });

But this code isn't getting executed when 'identity' isn't found. Perhaps it's because the loading of buffer into the new process's stdin causes a stack throw, halting the execution for future events e.g. the on('error') callback.

I'd imagine the maintainers may want to fix this