{"record":{"id":"78464520e9480731","repo":"lovell/sharp","slug":"expected-at-least-two-images-to-join","errorCode":null,"errorMessage":"Expected at least two images to join","messagePattern":"Expected at least two images to join","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/input.mjs","lineNumber":102,"sourceCode":"    inputOptions = input;\n    if (_inputOptionsFromObject(inputOptions)) {\n      // Stream with options\n      inputDescriptor.buffer = [];\n    }\n  } else if (!is.defined(input) && !is.defined(inputOptions) && is.object(containerOptions) && containerOptions.allowStream) {\n    // Stream without options\n    inputDescriptor.buffer = [];\n  } else if (Array.isArray(input)) {\n    if (input.length > 1) {\n      // Join images together\n      if (!this.options.joining) {\n        this.options.joining = true;\n        this.options.join = input.map(i => this._createInputDescriptor(i));\n      } else {\n        throw new Error('Recursive join is unsupported');\n      }\n    } else {\n      throw new Error('Expected at least two images to join');\n    }\n  } else {\n    throw new Error(`Unsupported input '${input}' of type ${typeof input}${\n      is.defined(inputOptions) ? ` when also providing options of type ${typeof inputOptions}` : ''\n    }`);\n  }\n  if (is.object(inputOptions)) {\n    // failOn\n    if (is.defined(inputOptions.failOn)) {\n      if (is.string(inputOptions.failOn) && is.inArray(inputOptions.failOn, ['none', 'truncated', 'error', 'warning'])) {\n        inputDescriptor.failOn = inputOptions.failOn;\n      } else {\n        throw is.invalidParameterError('failOn', 'one of: none, truncated, error, warning', inputOptions.failOn);\n      }\n    }\n    // autoOrient\n    if (is.defined(inputOptions.autoOrient)) {\n      if (is.bool(inputOptions.autoOrient)) {","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/lovell/sharp/blob/56676c69180a32b468123e090f87bfee30539b49/lib/input.mjs#L84-L120","documentation":"Thrown when the input to sharp is an array but contains fewer than two elements. The join feature stacks two or more images; a single-element or empty array has nothing to join. Sharp distinguishes this from 'Unsupported input' because the array branch is specifically for joins, and a one-image join is meaningless.","triggerScenarios":"Calling sharp([]) with an empty array, or sharp([singleImage]) with exactly one element. Dynamically building a join list that filters down to one or zero items at runtime: sharp(images.filter(Boolean)) where most are null.","commonSituations":"Filtering or slicing an image list before joining without checking the resulting length. Off-by-one errors when chunking. Empty result sets from a database query fed directly into sharp.","solutions":["Ensure the array has at least two valid image inputs before calling sharp.","Guard the length: if (images.length >= 2) sharp(images) else handleSingle(images[0]).","Filter defensively and assert the count before the join call."],"exampleFix":"// before\nsharp(images.filter(Boolean), { join: {} })\n\n// after\nconst valid = images.filter(Boolean);\nif (valid.length < 2) throw new Error('need >= 2 images to join');\nsharp(valid, { join: {} })","handlingStrategy":"validation","validationCode":"function joinInput(images) {\n  const valid = images.filter(Boolean);\n  if (valid.length < 2) throw new Error(`Join needs >= 2 images, got ${valid.length}`);\n  return valid;\n}\nsharp(joinInput(images), { join: {} });","typeGuard":"function isJoinableArray(input) {\n  return Array.isArray(input) && input.length >= 2;\n}","tryCatchPattern":null,"preventionTips":["Filter and assert length >= 2 before calling sharp with an array.","Handle the single-image case separately rather than relying on sharp to error.","Watch for empty arrays from queries/filters."],"tags":["join","input","validation","empty-array"],"backgroundTag":null,"analyzedSha":"56676c69180a32b468123e090f87bfee30539b49","analyzedAt":"2026-08-13T04:44:31.201Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}