{"record":{"id":"ff3daad9ad791995","repo":"Tencent/APIJSON","slug":"head-origin-substring-0-start","errorCode":null,"errorMessage":"HEAD请求: 字符 {origin.substring(0, start)} 不合法！预编译模式下 @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":2337,"sourceCode":"\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) {\n\t\t\t\tint index = c0 == null ? -1 : c0.lastIndexOf(\":\");\n\t\t\t\tif (index > 0) {\n\t\t\t\t\tc0 = c0.substring(0, index);\n\t\t\t\t}\n\n\t\t\t\tint start = c0 == null ? -1 : c0.indexOf(\"(\");\n\t\t\t\tint end = start <= 0 ? -1 : c0.lastIndexOf(\")\");","sourceCodeStart":2319,"sourceCodeEnd":2355,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2319-L2355","documentation":"Variant of the HEAD @column check: the item contains parentheses (so it is treated as a function call), but the function-name segment before '(' fails StringUtil.isName. In prepared mode the library requires the part before '(' to be one word, because it cannot safely parameterize an arbitrary pre-parenthesis token.","triggerScenarios":"HEAD request with \"@column\":\"date_format(date,'%Y-%m-%d')\" (the inner colons make lastIndexOf(':') split leave junk), \"@column\":\"schema.fun(id)\" (dotted prefix), or \"@column\":\"fun (id)\" (space before the parenthesis).","commonSituations":"Using MySQL formatting functions with format strings containing ':' which collide with the alias-splitting logic; writing SQL-style spacing (space between function name and '('); using schema-qualified functions.","solutions":["Remove spaces between the function name and '(': \"max(id)\" not \"max (id)\".","Avoid format strings containing ':' inside HEAD @column; register such expressions in @raw/RAW_MAP on the backend instead.","Do not qualify the function with a schema or package name — use the bare function name.","Simplify to a single plain column for HEAD counts."],"exampleFix":"// before\n{\"User\":{\"@column\":\"date_format(date,'%Y-%m-%d %H:%i:%s')\"}}\n// after (server-side RAW_MAP: \"dateFormat\" -> \"date_format(date,'%Y-%m-%d %H:%i:%s')\")\n{\"User\":{\"@column\":\"dateFormat\",\"@raw\":\"@column\"}}","handlingStrategy":"validation","validationCode":"const start = expr.indexOf('(');\nconst name = start > 0 ? expr.slice(0, start) : expr;\nif (start > 0 && !/^[A-Za-z][A-Za-z0-9_]*$/.test(name)) throw new Error('function token must be one word, no spaces before (');","typeGuard":"null","tryCatchPattern":"catch IllegalArgumentException; surface the offending token to the caller for correction","preventionTips":["No space between function name and '('","Avoid ':' characters in HEAD expressions; use @raw for date_format with time formats","Do not schema-qualify functions"],"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"}