{"record":{"id":"826ef0e63bc69301","repo":"jackwener/OpenCLI","slug":"unrecognized-a-share-symbol-input","errorCode":null,"errorMessage":"Unrecognized A-share symbol: ${input}","messagePattern":"Unrecognized A-share symbol: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clis/eastmoney/holders.js","lineNumber":25,"sourceCode":"import { CliError } from '@jackwener/opencli/errors';\n\n/**\n * Convert a bare A-share symbol to eastmoney's SECUCODE form (\"600519.SH\").\n * Accepts \"600519\", \"sh600519\", \"sz000001\", \"bj430047\", or full \"600519.SH\".\n * @param {string} input\n * @returns {string}\n */\nfunction toSecucode(input) {\n  const raw = String(input || '').trim().toUpperCase();\n  if (/^\\d{6}\\.(SH|SZ|BJ)$/.test(raw)) return raw;\n  const pref = raw.match(/^(SH|SZ|BJ)(\\d{6})$/);\n  if (pref) return `${pref[2]}.${pref[1]}`;\n  if (/^\\d{6}$/.test(raw)) {\n    if (/^(60|68|90|113|900)/.test(raw)) return `${raw}.SH`;\n    if (/^(4|8|920|83|87)/.test(raw))    return `${raw}.BJ`;\n    return `${raw}.SZ`;\n  }\n  throw new Error(`Unrecognized A-share symbol: ${input}`);\n}\n\ncli({\n  site: 'eastmoney',\n  name: 'holders',\n    access: 'read',\n  description: '十大流通股东（A股 F10 数据）',\n  domain: 'datacenter-web.eastmoney.com',\n  strategy: Strategy.PUBLIC,\n  browser: false,\n  args: [\n    { name: 'symbol', required: true, positional: true, help: 'A股代码（600519 / sh600519 等）' },\n    { name: 'limit',  type: 'int',    default: 10,      help: '返回股东数（默认十大流通股东）' },\n  ],\n  columns: ['rank', 'reportDate', 'name', 'holdNum', 'floatRatio', 'change'],\n  func: async (args) => {\n    /** @type {string} */\n    let secucode;","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/eastmoney/holders.js#L7-L43","documentation":"A plain Error (not CliError) thrown by the exported toSecucode() helper in clis/eastmoney/holders.js when a symbol cannot be mapped to an exchange-suffixed secucode. It accepts prefixed codes (e.g. 1.600519 / 0.000001) or bare 6-digit codes: 60/68/90/113/900 → .SH, 4/8/920/83/87 → .BJ, else .SZ. Anything failing both forms — letters, wrong length, unknown prefixes — reaches the throw at holders.js:25.","triggerScenarios":"Calling toSecucode or the holders CLI with 'AAPL', '60051' (5 digits), '6005190' (7 digits), '600.519', an empty string, or HK/US tickers that match neither the `pref` split nor `/^\\d{6}$/`.","commonSituations":"Users passing US/HK tickers instead of A-share codes, using 'sh600519'-style textual prefixes the parser doesn't handle, copy-paste artifacts (whitespace, full-width digits), or genuinely non-A-share instruments.","solutions":["Pass a standard 6-digit A-share code ('600519', '000001', '830799') or prefixed form '1.600519' / '0.000001'.","Trim and strip stray characters/prefixes from the symbol before calling.","Route non-A-share symbols to a different data source — toSecucode only handles SH/SZ/BJ.","Check your code's prefix against the SH/BJ lists; any other 6-digit code falls through to .SZ.","Validate with /^(\\d\\.)?\\d{6}$/ before calling and emit your own clearer message."],"exampleFix":"// before\nconst secucode = toSecucode(input); // throws on 'AAPL'\n// after\nconst raw = String(input ?? '').trim().replace(/^(sh|sz|bj)/i, '');\nif (!/^(\\d\\.)?\\d{6}$/.test(raw)) throw new CliError('INVALID_ARGUMENT', `Expected 6-digit A-share code, got: ${input}`);\nconst secucode = toSecucode(raw);","handlingStrategy":"validation","validationCode":"function normalizeAshareSymbol(input) {\n  const raw = String(input ?? '').trim();\n  if (/^\\d+\\.\\d{6}$/.test(raw)) return raw;            // 1.600519 form\n  if (/^\\d{6}$/.test(raw)) return raw;                  // bare code\n  throw new Error(`Expected A-share symbol (6-digit or N.XXXXXX), got: ${input}`);\n}","typeGuard":"/**\n * @param {unknown} input\n * @returns {input is string}\n */\nfunction isValidAshareSymbol(input) {\n  if (typeof input !== 'string') return false;\n  const s = input.trim();\n  return /^\\d+\\.\\d{6}$/.test(s) || /^\\d{6}$/.test(s);\n}","tryCatchPattern":"let secucode;\ntry {\n  secucode = toSecucode(input);\n} catch (err) {\n  console.error(`Invalid symbol '${input}': use a 6-digit A-share code (e.g. 600519) or N.XXXXXX form`);\n  process.exitCode = 1;\n  return;\n}","preventionTips":["Always pass 6-digit A-share codes or the N.XXXXXX prefixed form to this library.","Trim and normalize user input (strip 'sh'/'sz' prefixes, whitespace) before calling toSecucode.","Remember HK/US tickers are unsupported — route them to another data source.","Know the prefix map: 60/68/90/113/900=SH, 4/8/920/83/87=BJ, other 6-digit=SZ; anything non-conforming throws.","Unit-test toSecucode against your real symbol set before deploying."],"tags":["validation","input-parsing","symbol","eastmoney"],"backgroundTag":"invalid-symbol-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}