{"record":{"id":"75b217a080a4a68d","repo":"jackwener/OpenCLI","slug":"douyin-hashtag-search-keyword","errorCode":null,"errorMessage":"douyin hashtag search 需要 --keyword <关键词>","messagePattern":"douyin hashtag search 需要 --keyword <关键词>","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/douyin/hashtag.js","lineNumber":30,"sourceCode":"    }\n    const list = res[field];\n    if (list === undefined || list === null) return [];\n    if (!Array.isArray(list)) {\n        throw new CommandExecutionError(`douyin hashtag ${action}: API returned malformed \"${field}\"`);\n    }\n    return list;\n}\n\nfunction validateHashtagArgs(kwargs) {\n    const action = kwargs.action;\n    const limit = Number(kwargs.limit ?? 10);\n    if (!Number.isInteger(limit) || limit < 1) {\n        throw new ArgumentError(`--limit must be a positive integer, got ${JSON.stringify(kwargs.limit)}`);\n    }\n    if (action === 'search') {\n        const keyword = String(kwargs.keyword ?? '').trim();\n        if (!keyword) {\n            throw new ArgumentError('douyin hashtag search 需要 --keyword <关键词>', '示例: opencli douyin hashtag search --keyword 美食');\n        }\n        return;\n    }\n    if (action === 'suggest') {\n        const cover = String(kwargs.cover ?? '').trim();\n        if (!cover) {\n            throw new ArgumentError('douyin hashtag suggest 需要 --cover <cover_uri>', 'suggest 基于已上传的视频封面做 AI 推荐, 不是关键词搜索. 关键词搜索请用 `douyin hashtag search --keyword <词>`.');\n        }\n    }\n}\n\ncli({\n    site: 'douyin',\n    name: 'hashtag',\n    access: 'read',\n    description: '话题搜索 / AI推荐 / 热点词',\n    domain: 'creator.douyin.com',\n    strategy: Strategy.COOKIE,","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/hashtag.js#L12-L48","documentation":"The `search` action of `douyin hashtag` requires a non-empty keyword. validateHashtagArgs trims String(kwargs.keyword ?? '') and throws an ArgumentError with a usage example when it is empty. This is a required-argument guard, not an API failure.","triggerScenarios":"Running `douyin hashtag search` without `--keyword`, with `--keyword \"\"`, or with a whitespace-only value (`--keyword \"   \"` — trimmed to empty).","commonSituations":"Script variables that are empty/unset, forgetting the flag when copy-pasting commands, or confusing search (keyword-based) with suggest (cover-based).","solutions":["Provide a keyword: `opencli douyin hashtag search --keyword 美食`","Trim/validate the variable in your script before invoking","If you meant AI recommendations from a video cover, use the `suggest` action with --cover instead"],"exampleFix":"// before\nopencli douyin hashtag search --keyword \"$KW\"  // KW empty\n// after\nopencli douyin hashtag search --keyword \"${KW:?需要 --keyword}\"","handlingStrategy":"validation","validationCode":"const keyword = (process.env.KW ?? '').trim();\nif (!keyword) throw new Error('keyword is required for hashtag search');","typeGuard":"const hasKeyword = (kw) => typeof kw === 'string' && kw.trim().length > 0;","tryCatchPattern":"try {\n  await cli.hashtag({ action: 'search', keyword });\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.includes('search 需要 --keyword')) {\n    console.error('Usage: opencli douyin hashtag search --keyword <词>');\n  } else throw e;\n}","preventionTips":["Use ${VAR:?msg} in shell scripts to fail fast on empty variables","Trim keyword inputs before passing them on","Remember search requires --keyword; suggest requires --cover — pick the right action"],"tags":["validation","argument-error","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}