{"record":{"id":"ef996cf66a88306f","repo":"Tencent/APIJSON","slug":"head-origin-column-value-valu","errorCode":null,"errorMessage":"HEAD请求: 字符{origin} 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项 column:alias 中 column 必须是1个单词！如果有alias，则 alias 也必须为1个单词！并且不要有多余的空格！","messagePattern":"HEAD请求: 字符(.+?) 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项 column:alias 中 column 必须是1个单词！如果有alias，则 alias 也必须为1个单词！并且不要有多余的空格！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":2330,"sourceCode":"\t\t\t\t\t\t\t//column.remove(c);\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tint index = c.lastIndexOf(\":\"); //StringUtil.split返回数组中，子项不会有null\n\t\t\t\t\tString origin = index < 0 ? c : c.substring(0, index);\n\t\t\t\t\tString alias = index < 0 ? null : c.substring(index + 1);\n\n\t\t\t\t\tif (alias != null && StringUtil.isName(alias) == false) {\n\t\t\t\t\t\tthrow new IllegalArgumentException(\"HEAD请求: 字符 \" + alias\n\t\t\t\t\t\t\t\t+ \" 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项\"\n\t\t\t\t\t\t\t\t+ \" column:alias 中 column 必须是1个单词！如果有alias，则alias也必须为1个单词！并且不要有多余的空格！\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (StringUtil.isName(origin) == false) {\n\t\t\t\t\t\tint start = origin.indexOf(\"(\");\n\t\t\t\t\t\tif (start < 0 || origin.lastIndexOf(\")\") <= start) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"HEAD请求: 字符\" + origin\n\t\t\t\t\t\t\t\t\t+ \" 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项\"\n\t\t\t\t\t\t\t\t\t+ \" column:alias 中 column 必须是1个单词！\"\n\t\t\t\t\t\t\t\t\t+ \"如果有alias，则 alias 也必须为1个单词！并且不要有多余的空格！\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (start > 0 && StringUtil.isName(origin.substring(0, start)) == false) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(\"HEAD请求: 字符 \" + origin.substring(0, start)\n\t\t\t\t\t\t\t\t\t+ \" 不合法！预编译模式下 @column:value 中 value里面用 , 分割的每一项\"\n\t\t\t\t\t\t\t\t\t+ \" column:alias 中 column 必须是1个单词！如果有alias，则alias也必须为1个单词！并且不要有多余的空格！\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tboolean onlyOne = column != null && column.size() == 1;\n\t\t\tString c0 = onlyOne ? column.get(0) : null;\n\n\t\t\tif (onlyOne) {","sourceCodeStart":2312,"sourceCodeEnd":2348,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2312-L2348","documentation":"Thrown in the HEAD/HEADS branch of gainColumnString when, in prepared mode, the column part (text before the last ':') of an @column item fails StringUtil.isName and also does not look like a function call — there is no '(' or the ')' does not come after it. The library only accepts a plain identifier or a function(arg,...) form inside HEAD @column, so anything else is rejected as a potential injection vector.","triggerScenarios":"HEAD request with \"@column\":\"count(id\" (unbalanced parentheses), \"@column\":\"id+1\" (expression without parens), or \"@column\":\"user.id\" (dotted name is not a single word and has no function parens).","commonSituations":"Trying to count on a computed expression or a joined-table qualified column in a HEAD request; porting a GET query with complex @column to HEAD without simplifying; typo'd parentheses when hand-writing a function.","solutions":["Use a single column name: \"@column\":\"id\".","If a function is used, use the exact form fun(arg) with balanced parentheses, e.g. \"@column\":\"max(id)\".","Drop @column to get count(*).","For qualified or complex expressions, configure them as server-side @raw entries so the prepared-mode parser skips them."],"exampleFix":"// before\n{\"User\":{\"@column\":\"sum(id+1\"}}\n// after\n{\"User\":{\"@column\":\"sum(id)\"}}","handlingStrategy":"validation","validationCode":"const valid = /^[A-Za-z][A-Za-z0-9_]*(\\([^()]*\\))?$/.test(item);\nif (!valid) throw new Error('HEAD @column must be a word or fn(args)');","typeGuard":"null","tryCatchPattern":"catch IllegalArgumentException, map to 400, echo the accepted syntax to the caller","preventionTips":["Only single column names or fn(arg) forms in HEAD @column","Client-side paren balance check before send","No dotted or computed columns in count requests"],"tags":["apijson","sql","input-validation","prepared-statement","head-request"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}