{"record":{"id":"3a266e03559825bb","repo":"jackwener/OpenCLI","slug":"tid-must-be-a-numeric-thread-id","errorCode":null,"errorMessage":"tid must be a numeric thread id","messagePattern":"tid must be a numeric thread id","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/1point3acres/thread.js","lineNumber":35,"sourceCode":"cli({\n    site: '1point3acres',\n    name: 'thread',\n    access: 'read',\n    description: '一亩三分地 帖子详情 + 楼层（主楼 + 回复）',\n    domain: 'www.1point3acres.com',\n    strategy: Strategy.PUBLIC,\n    browser: false,\n    args: [\n        { name: 'tid', required: true, positional: true, help: '帖子 ID（数字，见 `hot`/`latest` 返回的 tid）' },\n        { name: 'page', type: 'int', default: 1, help: '楼层分页页码（默认 1）' },\n        { name: 'limit', type: 'int', default: 10, help: '返回楼层条数（默认 10，含主楼）' },\n        { name: 'contentLimit', type: 'int', default: 400, help: '每楼正文截断长度（默认 400 字符，最少 50）' },\n    ],\n    columns: ['floor', 'pid', 'author', 'postTime', 'content', 'url'],\n    func: async (args) => {\n        const tid = String(args.tid || '').trim();\n        if (!/^\\d+$/.test(tid)) {\n            throw new ArgumentError('tid must be a numeric thread id');\n        }\n        const page = normalizePositiveInteger(args.page, 1, 'page');\n        const limit = normalizePositiveInteger(args.limit, 10, 'limit');\n        const contentLimit = normalizePositiveInteger(args.contentLimit, 400, 'contentLimit', { min: 50 });\n\n        const url = `${BASE}/thread-${tid}-${page}-1.html`;\n        const html = await fetchHtml(url);\n\n        // Sanity: real thread page will contain postlist + at least one post div.\n        if (!/id=\"postlist\"/.test(html) && !/id=\"post_\\d+\"/.test(html)) {\n            throw new EmptyResultError('1point3acres thread', `帖子 ${tid} 不存在或被删除`);\n        }\n\n        // Split posts: each post block is bounded by <div id=\"post_<PID>\">…</div> next post or postlist end.\n        // NOTE: intermediate objects intentionally use postId/body/offset (not pid/html/start) to\n        // avoid being mistaken for row-shaped objects by the silent-column-drop audit.\n        const postBlocks = [];\n        const re = /<div id=\"post_(\\d+)\"[^>]*>/g;","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/1point3acres/thread.js#L17-L53","documentation":"ArgumentError thrown by the 1point3acres thread command when the `tid` argument is missing, empty, or not a pure decimal number. Thread ids in the site URLs (thread-<tid>-<page>-1.html) must be numeric, so the CLI validates strictly before building the request instead of producing a malformed URL.","triggerScenarios":"Calling the thread command with tid omitted, an empty string, whitespace, a thread slug/URL pasted instead of the id, or a non-numeric value like 'abc' or '123.4'.","commonSituations":"Pasting a full thread URL instead of the numeric tid; passing tid as a number with decimal or a string with units; forgetting the required argument in a script; shell quoting mangling the value.","solutions":["Pass the numeric thread id, e.g. tid: '2856313'","Extract the tid from a thread URL: thread-2856313-1-1.html → tid 2856313","Trim the input and ensure it matches /^\\d+$/ before calling","Do not pass a URL, slug, or decimal number as tid"],"exampleFix":"// before\nthread({ tid: 'https://www.1point3acres.com/bbs/thread-2856313-1-1.html' })\n// after\nconst tid = url.match(/thread-(\\d+)-/)?.[1];\nthread({ tid });","handlingStrategy":"validation","validationCode":"function isValidTid(tid) { return /^\\d+$/.test(String(tid ?? '').trim()); }\nif (!isValidTid(input)) { /* prompt/fix before calling */ }","typeGuard":"const isTid = (v) => typeof v === 'string' || typeof v === 'number';\nconst asTid = (v) => {\n  const s = String(v ?? '').trim();\n  return /^\\d+$/.test(s) ? s : null;\n};","tryCatchPattern":"try {\n  await thread({ tid });\n} catch (e) {\n  if (e instanceof ArgumentError && /tid/.test(e.message)) {\n    console.error('Provide the numeric thread id, e.g. thread-2856313-1-1.html → 2856313');\n  } else throw e;\n}","preventionTips":["Extract tid from pasted URLs with /thread-(\\d+)-/","Always String(x).trim() before validating","Never pass full URLs or slugs as tid"],"tags":["argument-validation","input-error","cli"],"backgroundTag":"invalid-argument","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}