{"record":{"id":"9f4542dd6934b3fc","repo":"jackwener/OpenCLI","slug":"unknown-tag-value","errorCode":null,"errorMessage":"Unknown tag: ${value}","messagePattern":"Unknown tag: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"warning","filePath":"clis/linux-do/feed.js","lineNumber":246,"sourceCode":"function topicListRichFromJson(data, limit) {\n    const topics = data?.topic_list?.topics ?? [];\n    return topics.slice(0, limit).map((t) => ({\n        title: t.fancy_title ?? t.title ?? '',\n        replies: normalizeReplyCount(t.posts_count),\n        created: toLocalTime(t.created_at),\n        likes: t.like_count ?? 0,\n        views: t.views ?? 0,\n        url: `https://linux.do/t/topic/${t.id}`,\n    }));\n}\n/**\n * 解析标签，支持 id、name、slug 三种输入。\n */\nasync function resolveTag(page, value) {\n    const liveTag = findMatchingTag(await fetchLiveTags(page), value);\n    if (liveTag)\n        return liveTag;\n    throw new ArgumentError(`Unknown tag: ${value}`, 'Use \"opencli linux-do tags\" to list available tags');\n}\n/**\n * 解析分类，并补齐父分类信息。\n */\nasync function resolveCategory(page, value) {\n    const liveCategory = findMatchingCategory(await fetchLiveCategories(page), value);\n    if (liveCategory)\n        return liveCategory;\n    throw new ArgumentError(`Unknown category: ${value}`, 'Use \"opencli linux-do categories\" to list available categories');\n}\n/**\n * 将命令参数转换为最终请求地址\n */\nasync function resolveFeedRequest(page, kwargs) {\n    const view = (kwargs.view || 'latest');\n    const period = (kwargs.period || 'weekly');\n    if (kwargs.period && view !== 'top') {\n        throw new ArgumentError('--period is only valid with --view top');","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/linux-do/feed.js#L228-L264","documentation":"resolveTag normalizes the user-supplied value and tries to match it against the live tag list (by id, name, or slug) fetched from linux.do; if no record matches it throws ArgumentError. The hint directs the user to `opencli linux-do tags` to enumerate valid tags. This is input validation, not a network failure — the tag list was retrieved successfully but nothing matched.","triggerScenarios":"`opencli linux-do feed --tag <value>` where value matches no tag id, name, or slug: typo, wrong casing/spacing beyond normalization, using a display name instead of slug, referencing a deleted tag, or passing a category name to --tag.","commonSituations":"Typing 'ChatGPT' when the slug is 'chatgpt' (handled) vs. a renamed/deleted tag; copying a tag title with extra punctuation; using an id from an outdated cached list; confusing tag with category values.","solutions":["Run `opencli linux-do tags` and copy the exact id, name, or slug from the output","Check for typos or removed tags; tags can be deleted or renamed on the forum","If you meant a category, use --category instead of --tag","Clear ~/.opencli/cache/linux-do/tags.json if you suspect the cached tag list is stale (TTL is 24h)"],"exampleFix":"// before (shell)\nopencli linux-do feed --tag \"AI 编程\"   // Unknown tag: AI 编程\n// after (shell)\nopencli linux-do tags                    # find the matching slug, e.g. 'ai-coding'\nopencli linux-do feed --tag ai-coding","handlingStrategy":"validation","validationCode":"import { execCommand } from './browser-runner.js';\n// Validate the tag before calling the feed command\nconst tags = await fetchLiveTags(page); // same list resolveTag uses\nfunction isValidTag(value) {\n    const norm = s => s.trim().replace(/\\s+/g, ' ').toLowerCase();\n    return tags.some(t =>\n        String(t.id) === value.trim() ||\n        norm(t.name) === norm(value) ||\n        norm(t.slug) === norm(value));\n}\nif (!isValidTag(userValue)) {\n    console.error('Invalid tag. Run: opencli linux-do tags');\n    process.exit(1);\n}","typeGuard":"function isKnownTag(records, value) {\n    const norm = s => String(s).trim().replace(/\\s+/g, ' ').toLowerCase();\n    return records.some(r =>\n        String(r.id) === value.trim() ||\n        norm(r.name) === norm(value) ||\n        norm(r.slug) === norm(value));\n}","tryCatchPattern":"import { ArgumentError } from '@jackwener/opencli/errors';\ntry {\n    await tag(value);\n} catch (err) {\n    if (err instanceof ArgumentError && err.message.startsWith('Unknown tag:')) {\n        console.error(`${err.message}\\n${err.hint || 'Run: opencli linux-do tags'}`);\n        process.exitCode = 1;\n    } else {\n        throw err;\n    }\n}","preventionTips":["Always pick tag values from `opencli linux-do tags` output rather than typing from memory","Prefer slug or numeric id over display names","Remember the CLI tolerates case/space differences but not punctuation or renamed tags","Clear the 24h tags cache after forum tag reorganizations"],"tags":["argument-validation","cli","user-input","not-found"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}