{"record":{"id":"9893ae5d9c2cfab8","repo":"jackwener/OpenCLI","slug":"title-is-title-length-chars-must-be-max-t","errorCode":null,"errorMessage":"Title is ${title.length} chars — must be ≤ ${MAX_TITLE_LEN}","messagePattern":"Title is (.+?) chars — must be ≤ (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/publish.js","lineNumber":1202,"sourceCode":"        const content = String(kwargs.content ?? '').trim();\n        const imagePaths = kwargs.images\n            ? String(kwargs.images).split(',').map((s) => s.trim()).filter(Boolean)\n            : [];\n        const topics = kwargs.topics\n            ? String(kwargs.topics).split(',').map((s) => s.trim()).filter(Boolean)\n            : [];\n        const isDraft = Boolean(kwargs.draft);\n        const cardText = kwargs['card-text'] ? String(kwargs['card-text']) : '';\n        const cards = cardText\n            ? cardText.split(CARD_TEXT_DELIM).map((s) => s.trim()).filter(Boolean)\n            : [];\n        const cardStyle = kwargs['card-style'] ? String(kwargs['card-style']).trim() : '';\n        const isTextImage = cards.length > 0;\n        // ── Validate inputs ────────────────────────────────────────────────────────\n        if (!title)\n            throw new ArgumentError('--title is required');\n        if (title.length > MAX_TITLE_LEN)\n            throw new ArgumentError(`Title is ${title.length} chars — must be ≤ ${MAX_TITLE_LEN}`);\n        if (!content)\n            throw new ArgumentError('Positional argument <content> is required');\n        if (!isTextImage && imagePaths.length === 0)\n            throw new ArgumentError('Provide --card-text (text-image mode) or --images (upload mode); neither was given.');\n        if (imagePaths.length > MAX_IMAGES)\n            throw new ArgumentError(`Too many images: ${imagePaths.length} (max ${MAX_IMAGES})`);\n        // The editor-page image input (text-image append) rejects gif.\n        if (isTextImage && imagePaths.some((p) => path.extname(p).toLowerCase() === '.gif'))\n            throw new ArgumentError('文字配图模式追加的图片不支持 .gif（编辑器图片入口只接受 jpg/jpeg/png/webp）');\n        // Validate image paths before navigating (fast-fail on bad paths / unsupported formats)\n        const absImagePaths = validateImagePaths(imagePaths);\n        // ── Step 1: Navigate to publish page ──────────────────────────────────────\n        await page.goto(PUBLISH_URL);\n        await page.wait({ time: 3 });\n        // Verify we landed on the creator site (not redirected to login)\n        const pageUrl = await page.evaluate('() => location.href');\n        if (!pageUrl.includes('creator.xiaohongshu.com')) {\n            throw new Error('Redirected away from creator center — session may have expired. ' +","sourceCodeStart":1184,"sourceCodeEnd":1220,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/publish.js#L1184-L1220","documentation":"ArgumentError thrown when the trimmed title exceeds MAX_TITLE_LEN (20 characters, matching XHS's title limit). The CLI validates length up front instead of letting the XHS editor truncate or reject it later.","triggerScenarios":"Running the publish command where `title.length > 20` after trimming — e.g. --title with a long sentence or non-CJK text that quickly exceeds 20 chars.","commonSituations":"English/long titles easily exceed 20 characters even when they feel short; pasting a full headline intended for the body into --title; not realizing XHS counts characters (including spaces/punctuation) toward the 20-char cap.","solutions":["Shorten the title to ≤ 20 characters","Move the extra text into --content (the body) instead of the title","Count characters first (e.g. `${#title}` in bash or title.length in JS) before running"],"exampleFix":"// before\n--title \"This is a way too long title for xiaohongshu\"\n// after\n--title \"短标题\" // body carries the detail","handlingStrategy":"validation","validationCode":"const title = rawTitle.trim();\nif (title.length > 20) throw new Error(`Title too long: ${title.length}/20`);","typeGuard":"function titleFits(t) {\n  return typeof t === 'string' && t.trim().length > 0 && t.trim().length <= 20;\n}","tryCatchPattern":"try {\n  await publish(page, { title, ...rest });\n} catch (e) {\n  if (String(e.message).includes('must be ≤')) {\n    title = title.slice(0, 20);\n    // retry with truncated title\n  } else throw e;\n}","preventionTips":["Keep titles ≤ 20 characters — XHS counts every char including spaces","Put long text in --content, not the title","Validate length in scripts before invoking the CLI"],"tags":["validation","cli-arguments","length-limit","xiaohongshu"],"backgroundTag":"input-length-exceeded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}