{"record":{"id":"b4c1a987c3daf682","repo":"Tencent/APIJSON","slug":"e-getkey-targettable-targetkey-targetkey","errorCode":null,"errorMessage":"${e.getKey()}:'/targetTable/targetKey' 中 targetKey 值 ${targetKey} 不合法！必须满足英文单词变量名格式！","messagePattern":"(.+?):'/targetTable/targetKey' 中 targetKey 值 (.+?) 不合法！必须满足英文单词变量名格式！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractParser.java","lineNumber":1819,"sourceCode":"\t\t\tif (arrKey != null) {\n\t\t\t\tInteger count = getInteger(parentPathObj, apijson.JSONRequest.KEY_COUNT);\n\t\t\t\tj.setCount(count == null ? getDefaultQueryCount() : count);\n\t\t\t}\n\n\t\t\tList<Join.On> onList = new ArrayList<>();\n\t\t\tfor (Entry<String, Object> refEntry : refSet) {\n\t\t\t\tString originKey = refEntry.getKey();\n\n\t\t\t\tString targetPath = (String) refEntry.getValue();\n\t\t\t\tif (StringUtil.isEmpty(targetPath, true)) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":value 中 value 值 \" + targetPath + \" 不合法！必须为引用赋值的路径 '/targetTable/targetKey' ！\");\n\t\t\t\t}\n\n\t\t\t\t// 取出引用赋值路径 targetPath 对应的 Table 和 key\n\t\t\t\tindex = targetPath.lastIndexOf(\"/\");\n\t\t\t\tString targetKey = index < 0 ? null : targetPath.substring(index + 1);\n\t\t\t\tif (StringUtil.isName(targetKey) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中 targetKey 值 \" + targetKey + \" 不合法！必须满足英文单词变量名格式！\");\n\t\t\t\t}\n\n\t\t\t\ttargetPath = targetPath.substring(0, index);\n\t\t\t\tindex = targetPath.lastIndexOf(\"/\");\n\t\t\t\tString targetTableKey = index < 0 ? targetPath : targetPath.substring(index + 1);\n\n\t\t\t\t// 主表允许别名\n\t\t\t\tapijson.orm.Entry<String, String> targetEntry = Pair.parseEntry(targetTableKey, true);\n\t\t\t\tString targetTable = targetEntry.getKey(); //User\n\t\t\t\tif (StringUtil.isName(targetTable) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable/targetKey' 中 targetTable 值 \" + targetTable + \" 不合法！必须满足大写字母开头的表对象英文单词 key 格式！\");\n\t\t\t\t}\n\n\t\t\t\tString targetAlias = targetEntry.getValue(); //owner\n\t\t\t\tif (StringUtil.isNotEmpty(targetAlias, true) && StringUtil.isName(targetAlias) == false) {\n\t\t\t\t\tthrow new IllegalArgumentException(e.getKey() + \":'/targetTable:targetAlias/targetKey' 中 targetAlias 值 \" + targetAlias + \" 不合法！必须满足英文单词变量名格式！\");\n\t\t\t\t}\n","sourceCodeStart":1801,"sourceCodeEnd":1837,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L1801-L1837","documentation":"The last segment of a reference path ('/targetTable/targetKey') is the target key and must satisfy StringUtil.isName. This IllegalArgumentException fires when targetKey is not a valid identifier — including the empty string when the path ends with '/', or null when the path has no '/' at all.","triggerScenarios":"'userId@': '/User/' (trailing slash -> empty targetKey), '/User/id()' (function-call suffix), '/User/user id' (space), or 'userId@': 'Userid' with no slash at all.","commonSituations":"Trailing slash typos; pasting remote-function keys ('fn()') into join paths; key names with spaces or punctuation copied from a spreadsheet.","solutions":["Fix the path to end with a valid identifier key: '/User/id'","Remove trailing slashes and any '()' function suffixes from reference paths used in joins"],"exampleFix":"// before\n{ 'join': '</Moment', 'Moment': { 'userId@': '/User/' } }\n// after\n{ 'join': '</Moment', 'Moment': { 'userId@': '/User/id' } }","handlingStrategy":"validation","validationCode":"const NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\nfunction checkRefTargets(req) {\n  for (const tbl of Object.values(req)) {\n    if (tbl && typeof tbl === 'object') {\n      for (const [k, v] of Object.entries(tbl)) {\n        if (!k.endsWith('@') || typeof v !== 'string') continue;\n        const key = v.substring(v.lastIndexOf('/') + 1);\n        if (!NAME_RE.test(key)) return `${k}: targetKey '${key}' in '${v}' is not a valid identifier`;\n      }\n    }\n  }\n  return null;\n}","typeGuard":"const isValidTargetKey = (p) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(p.substring(p.lastIndexOf('/') + 1));","tryCatchPattern":"Catch IllegalArgumentException containing 'targetKey 值'; fix/strip the malformed trailing path segment.","preventionTips":["Reference paths end with a clean identifier — no trailing '/', no '()' suffixes","Unit-test path builders against NAME_RE for both table and key segments"],"tags":["apijson","join","identifier","path-format"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}