{"record":{"id":"4de6c9c673739752","repo":"jackwener/OpenCLI","slug":"weibo-publish-text-exceeds-2000-characters","errorCode":null,"errorMessage":"weibo publish text exceeds 2000 characters","messagePattern":"weibo publish text exceeds 2000 characters","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/weibo/publish.js","lineNumber":47,"sourceCode":"const SUBMIT_POLL_MS = 500;\nconst SUBMIT_TIMEOUT_MS = 20_000;\nconst SUPPORTED_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp']);\n\n// Weibo PC UI selectors. The CSS-module hash drifts on every frontend\n// rebuild (#1602), so match on the stable placeholder text and keep the\n// legacy hash as a last-resort fallback. Callers pick the LAST visible\n// match because the compose modal renders on top of the home-feed strip.\nconst TEXTAREA_SELECTORS = [\n    'textarea[placeholder*=\"有什么新鲜事\"]',\n    'textarea[placeholder*=\"新鲜事\"]',\n    'textarea._input_13iqr_8',\n];\nconst FILE_INPUT_SELECTOR = 'input[type=\"file\"][class*=\"_file_\"]';\n\nfunction validateText(text) {\n    const t = String(text ?? '').trim();\n    if (!t) throw new ArgumentError('weibo publish text cannot be empty');\n    if (t.length > 2000) throw new ArgumentError('weibo publish text exceeds 2000 characters');\n    return t;\n}\n\nfunction validateImagePaths(raw) {\n    if (!raw) return [];\n    const paths = raw.split(',').map(s => s.trim()).filter(Boolean);\n    if (paths.length > MAX_IMAGES) {\n        throw new ArgumentError(`Too many images: ${paths.length} (max ${MAX_IMAGES})`);\n    }\n    return paths.map(p => {\n        const absPath = path.resolve(p);\n        const ext = path.extname(absPath).toLowerCase();\n        if (!SUPPORTED_EXTENSIONS.has(ext)) {\n            throw new ArgumentError(`Unsupported image format \"${ext}\". Supported: jpg, png, gif, webp`);\n        }\n        const stat = fs.statSync(absPath, { throwIfNoEntry: false });\n        if (!stat || !stat.isFile()) {\n            throw new ArgumentError(`Not a valid file: ${absPath}`);","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weibo/publish.js#L29-L65","documentation":"validateText enforces Weibo's practical length ceiling: trimmed text longer than 2000 characters is rejected with an ArgumentError before any browser interaction. Weibo truncates or rejects overly long posts, so the CLI fails early.","triggerScenarios":"Calling `weibo publish --text` with content whose trimmed length exceeds 2000 characters — e.g. pasting long articles or generated content.","commonSituations":"Scripting posts from files or LLM output without length checks; forgetting CJK-friendly trimming; concatenating content that pushes past the limit.","solutions":["Shorten the text to 2000 characters or fewer before publishing","Split the content into multiple posts","Add a pre-flight length check (text.trim().length <= 2000) in your pipeline"],"exampleFix":"// before\nweibo publish --text \"$LONG_TEXT\"\n// after\nTRIMMED=$(printf '%s' \"$LONG_TEXT\" | head -c 2000)\nweibo publish --text \"$TRIMMED\"","handlingStrategy":"validation","validationCode":"if (text.trim().length > 2000) {\n  throw new Error('text exceeds 2000 characters: ' + text.trim().length);\n}","typeGuard":"function isWithinLimit(v, max = 2000) {\n  return typeof v === 'string' && v.trim().length <= max;\n}","tryCatchPattern":"try {\n  await cli.run(['weibo', 'publish', '--text', text]);\n} catch (err) {\n  if (/exceeds 2000 characters/.test(err.message)) {\n    text = text.slice(0, 2000);\n    // retry with truncated text\n  } else throw err;\n}","preventionTips":["Truncate or split content to 2000 chars pre-flight","Check lengths of generated/concatenated content","Watch for multi-byte content inflating length"],"tags":["validation","argument-error","length-limit"],"backgroundTag":"input-length-exceeded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}