{"record":{"id":"2c61bf1b56388972","repo":"jackwener/OpenCLI","slug":"xianyu-publish-images-supports-at-most-max-image","errorCode":null,"errorMessage":"xianyu publish images supports at most ${MAX_IMAGES} files","messagePattern":"xianyu publish images supports at most (.+?) files","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/xianyu/publish.js","lineNumber":62,"sourceCode":"        throw new ArgumentError(`xianyu publish ${label} must be a positive price`);\n    }\n    return text;\n}\n\nfunction validateCondition(value) {\n    const condition = requireText(value, 'condition');\n    if (!CONDITION_CHOICES.includes(condition)) {\n        throw new ArgumentError(`xianyu publish condition must be one of: ${CONDITION_CHOICES.join(', ')}`);\n    }\n    return condition;\n}\n\nfunction validateImagePaths(raw) {\n    if (!raw) return [];\n    const paths = String(raw).split(',').map((item) => item.trim()).filter(Boolean);\n    if (paths.length === 0) return [];\n    if (paths.length > MAX_IMAGES) {\n        throw new ArgumentError(`xianyu publish images supports at most ${MAX_IMAGES} files`);\n    }\n    return paths.map((item) => {\n        const absPath = path.resolve(item);\n        const ext = path.extname(absPath).toLowerCase();\n        if (!SUPPORTED_IMAGE_EXTENSIONS.has(ext)) {\n            throw new ArgumentError(`Unsupported image format \"${ext}\". Supported: jpg, jpeg, png, webp`);\n        }\n        const stat = fs.statSync(absPath, { throwIfNoEntry: false });\n        if (!stat || !stat.isFile()) {\n            throw new ArgumentError(`Not a valid image file: ${absPath}`);\n        }\n        return absPath;\n    });\n}\n\nfunction normalizePublishArgs(kwargs) {\n    const price = parsePositivePrice(kwargs.price, 'price');\n    if (price == null) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xianyu/publish.js#L44-L80","documentation":"validateImagePaths throws ArgumentError when more than MAX_IMAGES (9) comma-separated image paths are supplied for xianyu publish. Xianyu listings allow at most 9 photos, so the library enforces the cap before any file I/O.","triggerScenarios":"Calling normalizePublishArgs with kwargs.images containing 10 or more comma-separated paths, e.g. 'a.jpg,b.jpg,...,j.jpg'.","commonSituations":"Bulk uploads of an entire product shoot (10+ photos), passing a whole directory listing as a comma-joined string, or scripts appending photos per product variant without deduplication.","solutions":["Trim the images list to 9 or fewer entries, keeping the best photos","Split into multiple listings if more than 9 photos are needed","Count paths before calling and truncate with images.split(',').slice(0, 9)"],"exampleFix":"// before\nawait publish({ images: paths.join(',') }); // paths.length = 12\n// after\nawait publish({ images: paths.slice(0, 9).join(',') });","handlingStrategy":"validation","validationCode":"const paths = String(images).split(',').map((s) => s.trim()).filter(Boolean);\nif (paths.length > 9) {\n  throw new Error(`images supports at most 9 files, got ${paths.length}`);\n}","typeGuard":"null","tryCatchPattern":"try {\n  await publish({ images });\n} catch (e) {\n  if (e instanceof ArgumentError && /at most 9 files/.test(e.message)) {\n    const kept = images.split(',').slice(0, 9).join(',');\n    await publish({ images: kept });\n  } else throw e;\n}","preventionTips":["Cap the photo list to 9 before invoking publish","De-duplicate paths so retries don't exceed the cap","Split oversized photo sets into multiple listings"],"tags":["validation","argument-error","images","limit"],"backgroundTag":"limit-exceeded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}