{"record":{"id":"e6dcdf18e6d1078f","repo":"Tencent/APIJSON","slug":"key-combine-value-get-head","errorCode":null,"errorMessage":"${key}:{} 里的 @combine:value 不合法！开放请求 GET、HEAD 才允许传 @combine:value !","messagePattern":"(.+?):(.+?) 里的 @combine:value 不合法！开放请求 GET、HEAD 才允许传 @combine:value !","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractParser.java","lineNumber":2481,"sourceCode":"\t\t\t\t\t\tsetRequestAttribute(key, false, KEY_VERSION, request);\n\t\t\t\t\t\tsetRequestAttribute(key, false, KEY_ROLE, request);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (key.startsWith(\"@\") || key.endsWith(\"@\")) {\n\t\t\t\t\tcorrectRequest.put(key, obj);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (obj instanceof Map<?, ?> || obj instanceof List<?>) {\n\t\t\t\t\tRequestMethod  _method;\n\t\t\t\t\tif (obj instanceof Map<?, ?>) {\n\t\t\t\t\t\tMap<String, Object> tblObj = JSON.getMap(request, key);\n\t\t\t\t\t\tString mn = tblObj == null ? null : getString(tblObj, KEY_METHOD);\n\t\t\t\t\t\t_method = mn == null ? null : RequestMethod.valueOf(mn);\n\t\t\t\t\t\tString combine = _method == null ? null : getString(tblObj, KEY_COMBINE);\n\t\t\t\t\t\tif (combine != null && RequestMethod.isPublicMethod(_method) == false) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(key + \":{} 里的 @combine:value 不合法！开放请求 GET、HEAD 才允许传 @combine:value !\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tMap<String, Object> attrMap = keyObjectAttributesMap.get(key);\n\n\t\t\t\t\t\tif (attrMap == null) {\n\t\t\t\t\t\t\tif (method == RequestMethod.CRUD) {\n\t\t\t\t\t\t\t\t_method = GET;\n\t\t\t\t\t\t\t\tMap<String, Object> objAttrMap = new HashMap<>();\n\t\t\t\t\t\t\t\tobjAttrMap.put(KEY_METHOD, GET);\n\t\t\t\t\t\t\t\tkeyObjectAttributesMap.put(key, objAttrMap);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t_method = method;\n\t\t\t\t\t\t\t\tMap<String, Object> objAttrMap = new HashMap<>();\n\t\t\t\t\t\t\t\tobjAttrMap.put(KEY_METHOD, method);\n\t\t\t\t\t\t\t\tkeyObjectAttributesMap.put(key, objAttrMap);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t_method = (RequestMethod) attrMap.get(KEY_METHOD);","sourceCodeStart":2463,"sourceCodeEnd":2499,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractParser.java#L2463-L2499","documentation":"AbstractParser rejects @combine inside a table object whose resolved operation method is not a public method (GET or HEAD). @combine builds OR/AND combinations of conditions and is only exposed for open read requests, so using it with POST/PUT/DELETE-style per-object methods throws IllegalArgumentException.","triggerScenarios":"A request to /get (or any endpoint) with a table object that declares a non-public method plus @combine, e.g. \"User\": {\"@method\": \"PUT\", \"@combine\": \"name|sex\"}; also CRUD endpoint where the object's own method resolves to PUT/POST/DELETE.","commonSituations":"Copying a GET request template into a write request and leaving @combine in; using the /crud endpoint where each object carries its own @method and trying to combine conditions on a write object.","solutions":["Remove @combine from objects whose method is not GET/HEAD","Or change that object's method to GET: \"@method\": \"GET\" if you only meant to read","For complex write conditions use @combine-free operators like key{} / key{}@ directly"],"exampleFix":"// before\n{\"User\": {\"@method\": \"PUT\", \"name~\": \"a\", \"sex\": 1, \"@combine\": \"name~|sex\"}}\n// after\n{\"User\": {\"@method\": \"GET\", \"name~\": \"a\", \"sex\": 1, \"@combine\": \"name~|sex\"}}","handlingStrategy":"validation","validationCode":"for (const [tbl, obj] of Object.entries(req)) {\n  if (obj && typeof obj === 'object' && '@combine' in obj) {\n    const m = (obj['@method'] ?? urlMethod).toUpperCase();\n    if (m !== 'GET' && m !== 'HEAD') throw new Error(`@combine not allowed with method ${m} on ${tbl}`);\n  }\n}","typeGuard":"const allowsCombine = m => ['GET', 'HEAD'].includes(String(m ?? '').toUpperCase());","tryCatchPattern":"try { await client.get(req); } catch (e) { if (e.message.includes('@combine')) deleteCombineAndRetry(req); else throw e; }","preventionTips":["Strip @combine in write-request templates","Treat @combine as a read-only feature in client typing (only on GET/HEAD request types)"],"tags":["apijson","combine","method-mismatch","security"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}