{"record":{"id":"5f9db3def48816df","repo":"jackwener/OpenCLI","slug":"visibility-missing","errorCode":null,"errorMessage":"填写抖音草稿表单失败: visibility-missing","messagePattern":"填写抖音草稿表单失败: visibility-missing","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/draft.js","lineNumber":119,"sourceCode":"      document.execCommand('selectAll', false);\n      document.execCommand('insertText', false, ${JSON.stringify(options.caption)});\n      editor.dispatchEvent(new Event('input', { bubbles: true }));\n      return true;\n    }`));\n        if (!captionOk) {\n            throw new CommandExecutionError('填写抖音草稿表单失败: caption-editor-missing');\n        }\n    }\n    const visibilityOk = (await page.evaluate(`() => {\n    const visibility = Array.from(document.querySelectorAll('label')).find(\n      (el) => (el.textContent || '').includes(${JSON.stringify(options.visibilityLabel)})\n    );\n    if (!(visibility instanceof HTMLElement)) return false;\n    visibility.click();\n    return true;\n  }`));\n    if (!visibilityOk) {\n        throw new CommandExecutionError('填写抖音草稿表单失败: visibility-missing');\n    }\n}\n/**\n * Switch the composer into custom-cover mode and expose the cover input with a\n * stable selector for CDP file injection.\n */\nasync function prepareCustomCoverInput(page) {\n    let lastReason = 'cover-input-missing';\n    const baselineCount = (await page.evaluate(`() => Array.from(document.querySelectorAll('input[type=\"file\"]')).length`));\n    for (let attempt = 0; attempt < COVER_INPUT_WAIT_ATTEMPTS; attempt += 1) {\n        const result = (await page.evaluate(`() => {\n      const coverLabel = Array.from(document.querySelectorAll('label')).find(\n        (el) => (el.textContent || '').includes('上传新封面')\n      );\n      if (coverLabel instanceof HTMLElement) {\n        coverLabel.click();\n      }\n","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/draft.js#L101-L137","documentation":"fillDraftComposer clicks a <label> whose text contains the visibility label ('公开' / '好友可见' / '仅自己可见'). If no matching label is found it throws this CommandExecutionError with reason 'visibility-missing'. The visibility section of the composer was not present or its text changed.","triggerScenarios":"Douyin composer renders visibility options as radio buttons/custom components without a <label> containing the expected Chinese text; the visibility section is collapsed or virtualized away; the '好友可见' label copy changed (e.g. to '好友圈').","commonSituations":"Douyin UI update renaming visibility options; new accounts with different default visibility UI; label rendered only after scrolling the page.","solutions":["Retry once in case the section rendered late","Inspect the composer page and update the visibility label text mapping (VISIBILITY_LABELS in clis/douyin/draft.js:12) or switch from 'label' to a broader selector like '[role=\"radio\"]'","Use the default --visibility public which matches the most stable '公开' label"],"exampleFix":"// before\nconst visibility = Array.from(document.querySelectorAll('label')).find(\n  (el) => (el.textContent || '').includes('好友可见')\n);\n// after: broader match\nconst visibility = Array.from(document.querySelectorAll('label,[role=\"radio\"]')).find(\n  (el) => /好友可见|好友圈/.test(el.textContent || '')\n);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await opencli.douyin.draft({ video, title, visibility: 'friends' });\n} catch (e) {\n  if (e.message.includes('visibility-missing')) {\n    // retry with default visibility 'public'\n    await opencli.douyin.draft({ video, title, visibility: 'public' });\n  }\n}","preventionTips":["Prefer the default 'public' visibility — its '公开' label is the most stable","Keep VISIBILITY_LABELS mapping in sync with live page copy","Fall back to default visibility instead of failing the whole draft"],"tags":["douyin","dom-selector","browser-automation"],"backgroundTag":"selector-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}