{"record":{"id":"afd213948dc05539","repo":"jackwener/OpenCLI","slug":"1000-afd213","errorCode":null,"errorMessage":"正文不能超过 1000 字","messagePattern":"正文不能超过 1000 字","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/douyin/publish.js","lineNumber":128,"sourceCode":"    columns: ['status', 'aweme_id', 'url', 'publish_time'],\n    func: async (page, kwargs) => {\n        // ── Fail-fast validation ────────────────────────────────────────────\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 fileSize = fs.statSync(videoPath).size;\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 timingTs = toUnixSeconds(kwargs.schedule);\n        validateTiming(timingTs);\n        const visibilityType = VISIBILITY_MAP[kwargs.visibility] ?? 0;\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        // ── Phase 1: upload credentials ────────────────────────────────────\n        const credentials = await getUploadAuthV5Credentials(page);\n        // ── Phase 2: Apply TOS upload URL ───────────────────────────────────\n        const tosUploadInfo = await applyVideoUploadInner(fileSize, credentials);\n        let coverUri = '';\n        let coverWidth = 720;\n        let coverHeight = 1280;\n        // ── Phase 3: TOS upload ─────────────────────────────────────────────","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/publish.js#L110-L146","documentation":"The douyin publish command validates the video caption (正文) length before starting the browser publish flow. Douyin caps captions at 1000 characters, so publish.js throws this ArgumentError pre-flight to avoid a rejected submission later in the platform's create_v2 call. It fails fast before any upload work happens.","triggerScenarios":"Calling the douyin publish command with kwargs.caption (or the caption CLI flag) set to a string whose .length exceeds 1000; no upload or browser interaction occurs — the throw is at the very start of the command.","commonSituations":"Users paste long video descriptions, marketing copy, or transcripts as the caption; content generated from templates that don't account for the 1000-char cap; non-ASCII text where users misjudge counts.","solutions":["Shorten the caption to 1000 characters or fewer before invoking publish","Trim programmatically: caption.slice(0, 1000) or move excess text into hashtags/description fields","Check caption.length before calling the command and surface a client-side validation message"],"exampleFix":"// before\nawait douyin.publish({ title: 'My video', caption: longCaption });\n// after\nconst caption = longCaption.length > 1000 ? longCaption.slice(0, 1000) : longCaption;\nawait douyin.publish({ title: 'My video', caption });","handlingStrategy":"validation","validationCode":"const caption = kwargs.caption ?? '';\nif (typeof caption !== 'string' || caption.length > 1000) {\n  throw new Error(`caption must be a string of at most 1000 chars, got ${caption.length}`);\n}","typeGuard":"function isValidCaption(v) {\n  return typeof v === 'string' && v.length <= 1000;\n}","tryCatchPattern":"try {\n  await douyin.publish({ title, caption });\n} catch (e) {\n  if (e instanceof ArgumentError && /正文不能超过/.test(e.message)) {\n    caption = caption.slice(0, 1000);\n    await douyin.publish({ title, caption });\n  } else throw e;\n}","preventionTips":["Validate caption length at input boundaries (CLI/config) before invoking publish","Truncate or summarize long descriptions automatically with a helper","Keep an eye on Douyin's documented limits; write them as shared constants"],"tags":["validation","argument-error","input-length"],"backgroundTag":"input-length-limit-exceeded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}