lovell/sharp · error · Error

Invalid convolution kernel

Error message

Invalid convolution kernel

What it means

Thrown by convolve() when the supplied kernel object fails any of a compound validation: it must be an object, kernel.kernel must be an array, width and height must be integers in range 3-1001, width*height must equal kernel.kernel.length, and every kernel element must be a number. Any single failure trips the whole check and rejects the kernel. Sharp needs a well-formed matrix to perform the convolution.

Solutions

  1. Provide width and height as integers between 3 and 1001 inclusive.
  2. Ensure kernel.kernel.length === width * height and every entry is a finite number.
  3. Start from a known-good kernel (e.g., a 3x3 box blur) and modify element values only.
  4. If loading kernels dynamically, coerce entries with Number() and validate before passing.

Example fix

// before
sharp(img).convolve({ kernel: [1,1,1,1,1,1,1,1,1] })

// after
sharp(img).convolve({ width: 3, height: 3, kernel: [1,1,1,1,1,1,1,1,1] })
Defensive patterns

Strategy: validation

Validate before calling

function validKernel(kernel) {
  if (!kernel || !Array.isArray(kernel.kernel)) throw new Error('kernel.kernel must be an array');
  if (!Number.isInteger(kernel.width) || !Number.isInteger(kernel.height)) throw new Error('width/height must be integers');
  if (kernel.width < 3 || kernel.width > 1001 || kernel.height < 3 || kernel.height > 1001) throw new Error('width/height must be in [3,1001]');
  if (kernel.width * kernel.height !== kernel.kernel.length) throw new Error('kernel length must equal width*height');
  if (!kernel.kernel.every(n => typeof n === 'number' && Number.isFinite(n))) throw new Error('all kernel values must be finite numbers');
  return true;
}

Type guard

function isValidConvolutionKernel(k) {
  return !!k && typeof k === 'object' && Array.isArray(k.kernel) &&
    Number.isInteger(k.width) && Number.isInteger(k.height) &&
    k.width >= 3 && k.width <= 1001 && k.height >= 3 && k.height <= 1001 &&
    k.width * k.height === k.kernel.length &&
    k.kernel.every(n => typeof n === 'number' && Number.isFinite(n));
}

Prevention

When it happens

Trigger: convolve({ kernel: [1,1,1,1,1,1,1,1,1] }) missing width/height. convolve({ width: 3, height: 3, kernel: [1,1,1] }) (length 3 != 9). convolve({ width: 2, height: 2, kernel: [1,1,1,1] }) (width out of range 3-1001). kernel containing a non-number like null or a string.

Common situations: Hand-writing a kernel and miscounting elements. Using width/height of 2 thinking 2x2 is allowed (minimum is 3). Loading a kernel from JSON where numbers became strings. Off-by-one in generated kernels.

Related errors


AI-assisted analysis of lovell/sharp@56676c6918 (2026-08-13). Data as JSON: /api/errors/7858b85d0ea3b9d5. Report an issue: GitHub.

Appendix: source

Thrown at lib/operation.mjs:719

 *
 * @param {Object} kernel
 * @param {number} kernel.width - width of the kernel in pixels.
 * @param {number} kernel.height - height of the kernel in pixels.
 * @param {Array<number>} kernel.kernel - Array of length `width*height` containing the kernel values.
 * @param {number} [kernel.scale=sum] - the scale of the kernel in pixels.
 * @param {number} [kernel.offset=0] - the offset of the kernel in pixels.
 * @returns {Sharp}
 * @throws {Error} Invalid parameters
 */
function convolve (kernel) {
  if (!is.object(kernel) || !Array.isArray(kernel.kernel) ||
      !is.integer(kernel.width) || !is.integer(kernel.height) ||
      !is.inRange(kernel.width, 3, 1001) || !is.inRange(kernel.height, 3, 1001) ||
      kernel.height * kernel.width !== kernel.kernel.length ||
      !kernel.kernel.every(is.number)
  ) {
    // must pass in a kernel
    throw new Error('Invalid convolution kernel');
  }
  // Default scale is sum of kernel values
  if (!is.integer(kernel.scale)) {
    kernel.scale = kernel.kernel.reduce((a, b) => a + b, 0);
  }
  // Clip scale to a minimum value of 1
  if (kernel.scale < 1) {
    kernel.scale = 1;
  }
  if (!is.integer(kernel.offset)) {
    kernel.offset = 0;
  }
  this.options.convKernel = kernel;
  return this;
}

/**
 * Any pixel value greater than or equal to the threshold value will be set to 255, otherwise it will be set to 0.

View on GitHub (pinned to 56676c6918)