{"record":{"id":"0dd483ef308c5880","repo":"langgenius/dify","slug":"name-must-be-a-non-empty-string-array","errorCode":null,"errorMessage":"${name} must be a non-empty string array","messagePattern":"(.+?) must be a non-empty string array","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"sdks/nodejs-client/src/client/validation.ts","lineNumber":56,"sourceCode":"    return\n  }\n  if (!Number.isInteger(value)) {\n    throw new ValidationError(`${name} must be an integer when set`)\n  }\n}\n\nexport function ensureOptionalBoolean(value: unknown, name: string): void {\n  if (value === undefined || value === null) {\n    return\n  }\n  if (typeof value !== 'boolean') {\n    throw new ValidationError(`${name} must be a boolean when set`)\n  }\n}\n\nexport function ensureStringArray(value: unknown, name: string): void {\n  if (!Array.isArray(value) || value.length === 0) {\n    throw new ValidationError(`${name} must be a non-empty string array`)\n  }\n  if (value.length > MAX_LIST_LENGTH) {\n    throw new ValidationError(`${name} exceeds maximum size of ${MAX_LIST_LENGTH} items`)\n  }\n  value.forEach((item) => {\n    if (typeof item !== 'string' || item.trim().length === 0) {\n      throw new ValidationError(`${name} must contain non-empty strings`)\n    }\n  })\n}\n\nexport function ensureOptionalStringArray(value: unknown, name: string): void {\n  if (value === undefined || value === null) {\n    return\n  }\n  ensureStringArray(value, name)\n}\n","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/sdks/nodejs-client/src/client/validation.ts#L38-L74","documentation":"Thrown by ensureStringArray() in validation.ts:56 as a ValidationError. The value must be a non-empty Array; this guard runs first, before the per-item and length-cap checks. It is used for fields like tagIds on listDatasets.","triggerScenarios":"Calling kb.listDatasets({ tagIds: undefined }) after the upstream check at knowledge-base.ts:70 already short-circuits length>0, but if reached directly via ensureStringArray: { tagIds: 'single' } (string not array), { tagIds: [] }, { tagIds: null }, { tagIds: {} }.","commonSituations":"Passing a single id string instead of an array; mapping a list that produced []; JSON-decoding a missing field into null; sharing one variable across multiple optionals.","solutions":["Wrap singles in an array: kb.listDatasets({ tagIds: [tagId] }).","Omit the field or guard upstream: const tagIds = ids.length ? ids : undefined.","Ensure JSON sources decode to arrays even for one element."],"exampleFix":"// before\nawait kb.listDatasets({ tagIds: singleTagId })\n\n// after\nawait kb.listDatasets({ tagIds: [singleTagId] })","handlingStrategy":"validation","validationCode":"function toNonEmptyStringArray(value: unknown): string[] {\n  if (!Array.isArray(value) || value.length === 0) throw new Error('must be a non-empty array')\n  return value as string[]\n}","typeGuard":"function isNonEmptyStringArray(value: unknown): value is string[] {\n  return Array.isArray(value) && value.length > 0\n}","tryCatchPattern":"try {\n  await kb.listDatasets({ tagIds })\n} catch (err) {\n  if (err instanceof Error && /non-empty string array/.test(err.message)) {\n    // wrap single value or skip\n    await kb.listDatasets({ tagIds: [tagIds as string] })\n  } else throw err\n}","preventionTips":["Always pass arrays even for a single value: [singleId].","Omit the field when the list is empty rather than passing [].","Type the field as string[] (not string | string[])."],"tags":["validation","array","string-array","tags","required-field"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}