{"record":{"id":"4e78e016bb3530d4","repo":"Tencent/APIJSON","slug":"error-4e78e0","errorCode":null,"errorMessage":"写操作请求必须带条件！！！","messagePattern":"写操作请求必须带条件！！！","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":400,"severity":"critical","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":3396,"sourceCode":"\t\t\treturn getWhereString(hasPrefix, getMethod(), getWhere(), getCombineMap(), getJoinList(), ! isTest());\n\t\t}\n\t\treturn getWhereString(hasPrefix, getMethod(), getWhere(), combineExpr, getJoinList(), ! isTest());\n\t}\n\t/**获取WHERE\n\t * @param method\n\t * @param where\n\t * @return\n\t * @throws Exception\n\t */\n\tpublic String getWhereString(boolean hasPrefix, RequestMethod method, Map<String, Object> where\n\t\t\t, String combine, List<Join<T, M, L>> joinList, boolean verifyName) throws Exception {\n\t\tString whereString = parseCombineExpression(method, getQuote(), getTable(), getAlias()\n\t\t\t\t, where, combine, verifyName, false, false);\n\t\twhereString = concatJoinWhereString(whereString);\n\t\tString result = StringUtil.isEmpty(whereString, true) ? \"\" : (hasPrefix ? \" WHERE \" : \"\") + whereString;\n\n\t\tif (result.isEmpty() && RequestMethod.isQueryMethod(method) == false) {\n\t\t\tthrow new UnsupportedOperationException(\"写操作请求必须带条件！！！\");\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**解析 @combine 条件 key 组合的与或非+括号的逻辑运算表达式为具体的完整条件组合\n\t * @param method\n\t * @param quote\n\t * @param table\n\t * @param alias\n\t * @param conditionMap  where 或 having 对应条件的 Map\n\t * @param combine\n\t * @param verifyName\n\t * @param containRaw\n\t * @param isHaving\n\t * @return\n\t * @throws Exception\n\t */","sourceCodeStart":3378,"sourceCodeEnd":3414,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L3378-L3414","documentation":"getWhereString() builds the WHERE clause from the where map + @combine; if the result is empty AND the request method is not a query method (isQueryMethod covers GET/HEAD and similar), it throws UnsupportedOperationException. APIJSON deliberately forbids unconditional writes/updates/deletes — an UPDATE or DELETE with no WHERE would affect every row in the table.","triggerScenarios":"A PUT/DELETE request (per APIJSON method mapping) whose table object contains no condition keys at all, e.g. {\"User\":{\"name\":\"a\"}} on DELETE where the keys are all consumed as SET columns, or conditions that all resolve to empty (e.g. @combine referencing no effective keys). RequestMethod.isQueryMethod(method) == false is what activates the check at line 3395.","commonSituations":"Forgetting the id in an update/delete request; building the request dynamically so the condition object ends up empty; migrating a GET-style request to PUT without adding a where key; test scripts that mass-update by intent and hit the safety guard.","solutions":["Add an explicit condition key to the write request, almost always the primary key: {\"User\":{\"id\":1,\"name\":\"x\"}} for PUT or {\"User\":{\"id\":1}} for DELETE.","If a genuinely global operation is required, do it with a raw/ADMIN-authorized endpoint or a stored procedure — do not try to bypass this guard in ORM code.","When building requests programmatically, assert the condition map is non-empty before sending (see validation code).","Check that your conditions are not silently dropped (e.g. misspelled keys filtered by request structure) leaving an empty WHERE."],"exampleFix":"// before (DELETE everything)\n{\"User\":{}}\n// after (DELETE one row)\n{\"User\":{\"id\":1}}","handlingStrategy":"try-catch","validationCode":"RequestMethod m = parser.getMethod();\nif (!RequestMethod.isQueryMethod(m)) {\n    JSONObject table = request.getJSONObject(\"User\");\n    boolean hasCondition = table.keySet().stream().anyMatch(k -> !k.startsWith(\"@\"));\n    if (!hasCondition) throw new IllegalStateException(\"write request needs a where key (e.g. id)\");\n}","typeGuard":"function hasWriteCondition(req: Record<string, any>): boolean {\n  return Object.keys(req).some(k => !k.startsWith('@')); // at least one condition key present\n}","tryCatchPattern":"try { parser.execute(...); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"写操作请求必须带条件\")) { /* surface 'missing WHERE' to user, never retry blindly */ } throw e; }","preventionTips":["Always include the primary key in PUT/DELETE request objects.","Assert non-empty condition map before sending any non-query request.","Treat this exception as a hard stop — it prevented a full-table write."],"tags":["apijson","data-safety","write-protection","where-clause","security"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}