{"record":{"id":"f8107a483e553f7c","repo":"Tencent/APIJSON","slug":"raw-value-value-key-key-value-v","errorCode":null,"errorMessage":"@raw:value 的 value 中 {key} 不合法！对应的 {key}:value 中 value 类型只能为 String！","messagePattern":"@raw:value 的 value 中 (.+?) 不合法！对应的 (.+?):value 中 value 类型只能为 String！","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":2238,"sourceCode":"\t\treturn gainRawSQL(key, value, ! ALLOW_MISSING_KEY_4_COMBINE);\n\t}\n\t/**获取原始 SQL 片段\n\t * @param key\n\t * @param value\n\t * @param throwWhenMissing\n\t * @return\n\t * @throws Exception\n\t */\n\t@Override\n\tpublic String gainRawSQL(String key, Object value, boolean throwWhenMissing) throws Exception {\n\t\tif (value == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tList<String> rawList = getRaw();\n\t\tboolean containRaw = rawList != null && rawList.contains(key);\n\t\tif (containRaw && value instanceof String == false) {\n\t\t\tthrow new UnsupportedOperationException(\"@raw:value 的 value 中 \" + key + \" 不合法！\"\n\t\t\t\t\t+ \"对应的 \" + key + \":value 中 value 类型只能为 String！\");\n\t\t}\n\n\t\tString rawSQL = containRaw ? RAW_MAP.get(value) : null;\n\t\tif (containRaw) {\n\t\t\tif (rawSQL == null) {\n\t\t\t\tif (throwWhenMissing) {\n\t\t\t\t\tthrow new UnsupportedOperationException(\"@raw:value 的 value 中 \" + key + \" 不合法！\"\n\t\t\t\t\t\t\t+ \"对应的 \" + key + \":value 中 value 值 \" + value + \" 未在后端 RAW_MAP 中配置 ！\");\n\t\t\t\t}\n\n\t\t\t\tputWarnIfNeed(JSONMap.KEY_RAW, \"@raw:value 的 value 中 \"\n\t\t\t\t\t\t\t+ key + \" 不合法！对应的 \" + key + \":value 中 value 值 \" + value + \" 未在后端 RAW_MAP 中配置 ！\");\n\t\t\t}\n\t\t\telse if (rawSQL.isEmpty()) {\n\t\t\t\treturn (String) value;\n\t\t\t}\n\t\t}","sourceCodeStart":2220,"sourceCodeEnd":2256,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L2220-L2256","documentation":"gainRawSQL throws when @raw lists a key (e.g. \"@raw\": [\"@column\"]) but the corresponding sibling value in the request is not a String. @raw means 'insert the matching value's pre-approved SQL from RAW_MAP', and RAW_MAP keys are strings — a non-string value can never match and is rejected up front.","triggerScenarios":"{\"@raw\": \"@having\", \"@having\": 123} or \"@having\": [\"a\"] — the referenced key exists in @raw but its value is a number/array/object instead of a String.","commonSituations":"Client sets the @raw-flagged field from untyped form input that arrives as a number; renaming fields so @raw points at a field that now holds structured data.","solutions":["Make the @raw-referenced value a string: \"@having\": \"myFilter\"","Ensure the string is a key configured in backend RAW_MAP","Keep @raw list and the flagged fields in sync when renaming keys"],"exampleFix":"// before\n{\"@raw\": \"@having\", \"@having\": 123}\n// after\n{\"@raw\": \"@having\", \"@having\": \"myFilter\"}","handlingStrategy":"type-guard","validationCode":"const rawList = Array.isArray(obj['@raw']) ? obj['@raw'] : (obj['@raw'] ? [obj['@raw']] : []);\nfor (const k of rawList) {\n  if (k in obj && typeof obj[k] !== 'string') throw new Error(`@raw target ${k} must hold a string token, got ${typeof obj[k]}`);\n}","typeGuard":"const isRawTargetString = (obj, k) => typeof obj[k] === 'string';","tryCatchPattern":"try { await api.get(req); } catch (e) { if (e.message.includes('value 类型只能为 String')) coerceRawTargetsToString(req); else throw e; }","preventionTips":["Type @raw-flagged fields as string in client models","Never let numeric form input flow untyped into a @raw-referenced field"],"tags":["apijson","raw","type-error"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}