{"record":{"id":"9fc3b48697547947","repo":"jackwener/OpenCLI","slug":"1000","errorCode":null,"errorMessage":"正文不能超过 1000 字","messagePattern":"正文不能超过 1000 字","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/douyin/draft.js","lineNumber":321,"sourceCode":"        { name: 'visibility', default: 'public', choices: ['public', 'friends', 'private'] },\n    ],\n    columns: ['status', 'draft_id'],\n    func: async (page, kwargs) => {\n        const videoPath = path.resolve(kwargs.video);\n        if (!fs.existsSync(videoPath)) {\n            throw new ArgumentError(`视频文件不存在: ${videoPath}`);\n        }\n        const ext = path.extname(videoPath).toLowerCase();\n        if (!['.mp4', '.mov', '.avi', '.webm'].includes(ext)) {\n            throw new ArgumentError(`不支持的视频格式: ${ext}（支持 mp4/mov/avi/webm）`);\n        }\n        const title = kwargs.title;\n        if (title.length > 30) {\n            throw new ArgumentError('标题不能超过 30 字');\n        }\n        const caption = kwargs.caption || '';\n        if (caption.length > 1000) {\n            throw new ArgumentError('正文不能超过 1000 字');\n        }\n        const coverPath = kwargs.cover;\n        if (coverPath) {\n            if (!fs.existsSync(path.resolve(coverPath))) {\n                throw new ArgumentError(`封面文件不存在: ${path.resolve(coverPath)}`);\n            }\n        }\n        if (!page.setFileInput) {\n            throw new CommandExecutionError('当前浏览器适配器不支持文件注入', '请使用 Browser Bridge 或支持 setFileInput 的浏览器模式');\n        }\n        const visibilityLabel = VISIBILITY_LABELS[kwargs.visibility] ?? VISIBILITY_LABELS.public;\n        await page.goto(DRAFT_UPLOAD_URL);\n        await page.wait({ selector: 'input[type=\"file\"]', timeout: 20 });\n        await dismissKnownModals(page);\n        await page.setFileInput([videoPath], 'input[type=\"file\"]');\n        await waitForDraftComposer(page);\n        await dismissKnownModals(page);\n        if (coverPath) {","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/draft.js#L303-L339","documentation":"The caption (正文) field is capped at 1000 characters by the draft command. If kwargs.caption (defaulting to '') has .length > 1000, an ArgumentError is thrown before the browser session starts.","triggerScenarios":"Passing --caption or caption kwarg with more than 1000 characters — long descriptions, pasted articles, many hashtags and mentions concatenated.","commonSituations":"Cross-posting long-form descriptions from other platforms, programmatically generated captions with repeated hashtag blocks, or template expansion blowing past the cap.","solutions":["Shorten the caption to ≤1000 characters","Truncate in code before calling: `[...caption].slice(0, 1000).join('')`","Move long-form content into the video itself or a pinned comment instead of the caption"],"exampleFix":"// before\nconst caption = longDescription; // 1500 chars\n// after\nconst caption = [...longDescription].slice(0, 1000).join('');","handlingStrategy":"validation","validationCode":"if ([...caption].length > 1000) throw new Error('Caption exceeds 1000-char Douyin limit');","typeGuard":null,"tryCatchPattern":"try {\n  await cli.draft({ caption, video, title });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('正文不能超过')) {\n    await cli.draft({ caption: [...caption].slice(0, 1000).join(''), video, title });\n  } else throw e;\n}","preventionTips":["Truncate cross-posted descriptions to 1000 chars before calling","Move long-form content to a pinned comment or the video itself","Count with [...str].length to handle emoji/surrogate pairs correctly"],"tags":["validation","argument-error","limit-exceeded"],"backgroundTag":"input-length-limit","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}