NodeJS
gm module
image size
synchronous processing
JavaScript

NodeJS gm getting image size synchronously

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The gm module is built around asynchronous process execution, so it does not offer a normal synchronous sizeSync() API. If you truly need synchronous image-size lookup in Node.js, the practical options are to call the underlying GraphicsMagick or ImageMagick CLI synchronously, or use a different library that already supports synchronous metadata reads.

What gm Normally Does

With gm, the standard way to read dimensions is asynchronous:

javascript
1const gm = require("gm");
2
3gm("photo.jpg").size((err, size) => {
4  if (err) throw err;
5  console.log(size.width, size.height);
6});

That fits Node's normal event-loop model, which is why the package does not emphasize blocking APIs.

There Is No Native Synchronous gm Call

If you are looking for something like:

javascript
const size = gm("photo.jpg").sizeSync();

that API does not exist in the gm package. The package is a wrapper around external tools, and its public methods are callback-based or stream-based.

So the real question becomes: how do you get the same information synchronously if blocking is truly required?

Call the CLI Synchronously

If GraphicsMagick is installed, you can call gm identify through execFileSync.

javascript
1const { execFileSync } = require("node:child_process");
2
3function getImageSizeSync(filePath) {
4  const output = execFileSync(
5    "gm",
6    ["identify", "-format", "%w %h", filePath],
7    { encoding: "utf8" }
8  ).trim();
9
10  const [width, height] = output.split(" ").map(Number);
11  return { width, height };
12}
13
14console.log(getImageSizeSync("photo.jpg"));

This is synchronous because execFileSync blocks until the external command finishes.

It also keeps you close to the real tool that gm would call under the hood. If the command works in a terminal, you can usually reproduce the same behavior from Node and debug path or installation problems more directly.

Handle Failures Explicitly

Real image pipelines need to handle missing files, unreadable formats, and missing binaries. A small wrapper makes that behavior clearer:

javascript
1const { execFileSync } = require("node:child_process");
2
3function safeImageSizeSync(filePath) {
4  try {
5    const output = execFileSync(
6      "gm",
7      ["identify", "-format", "%w %h", filePath],
8      { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }
9    ).trim();
10
11    const [width, height] = output.split(" ").map(Number);
12    return { width, height };
13  } catch (error) {
14    throw new Error(`Could not inspect image: ${filePath}`);
15  }
16}

That pattern is easier to reason about than assuming every file is valid and every machine has GraphicsMagick installed correctly.

Understand the Tradeoff

Synchronous image inspection blocks the Node.js event loop. That means:

  • Other requests do not progress during the call
  • Throughput drops under load
  • Slow disk or image commands affect the whole process

That is acceptable for build scripts, CLIs, or one-time startup work. It is usually a poor fit for a busy HTTP server unless the blocking cost is negligible and you fully understand the impact.

Sometimes a Different Library Is Better

If your only goal is "read width and height," you may not need gm at all. A metadata-focused library with a simpler API can be a better choice than forcing gm into a synchronous role.

The main point is architectural: if you want synchronous metadata reads, pick a tool that naturally supports them rather than fighting a wrapper that was built for async execution.

That is especially true in newer Node codebases where image metadata is a small preprocessing step rather than the center of the application.

Common Pitfalls

  • Expecting gm to expose a built-in synchronous size API leads to dead ends because that method is not part of the package.
  • Using execSync or execFileSync in a request handler can block the entire Node.js process.
  • Passing untrusted file paths into shell-style commands can create command-injection risk; prefer execFileSync with argument arrays over interpolated shell strings.
  • Forgetting that gm requires GraphicsMagick or ImageMagick to be installed causes confusing runtime failures unrelated to Node itself.

If blocking is unavoidable, doing the work in a separate worker process is often safer than freezing the main event loop. That gives you isolation as well.

Summary

  • 'gm does not provide a normal synchronous size API.'
  • If you truly need blocking behavior, call the underlying gm identify command with execFileSync.
  • Use that pattern sparingly because synchronous work blocks the Node.js event loop.
  • For simple metadata reads, consider whether a different image library is a better fit.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.