{"record":{"id":"1c9a811781784652","repo":"Tencent/APIJSON","slug":"error","errorCode":null,"errorMessage":"批量新增/修改失败！{}/{}：{}","messagePattern":"批量新增/修改失败！(.+?)/(.+?)：(.+?)","errorType":"exception","errorClass":"ServerException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java","lineNumber":868,"sourceCode":"            }\n\n            result = result == null ? null : JSON.get(result, childKey);\n\n            boolean success = JSONResponse.isSuccess(result);\n            int count = result == null ? 0 : getIntValue(result, JSONResponse.KEY_COUNT);\n            if (id == null && result != null) {\n                id = result.get(idKey);\n            }\n\n            if (success == false || count != 1) { //如果 code = 200 但 count != 1，不能算成功，掩盖了错误不好排查问题\n                if (allowPartialFailed) {\n                    failedIds.add(id);\n                    if (firstFailIndex < 0) {\n                        firstFailIndex = i;\n                    }\n                }\n                else {\n                    throw new ServerException(\n                            \"批量新增/修改失败！\" + key + \"/\" + i + \"：\" + (success ? \"成功但 count != 1 ！\"\n                                    : (result == null ? \"null\" : getString(result, JSONResponse.KEY_MSG))\n                    ));\n                }\n            }\n\n\t\t\tallCount += 1; // 加了 allowPartialFailed 后 count 可能为 0  allCount += count;\n\t\t\tids.add(id);\n\t\t}\n\n        int failedCount = failedIds == null ? 0 : failedIds.size();\n        if (failedCount > 0 && failedCount >= allCount) {\n            throw new ServerException(\"批量新增/修改 \" + key + \":[] 中 \" + allCount + \" 个子项全部失败！\"\n                    + \"第 \" + firstFailIndex + \" 项失败原因：\" + (firstFailThrow == null ? \"\" : firstFailThrow.getMessage()));\n        }\n\n        M allResult = getParser().newSuccessResult();\n        if (failedCount > 0) {","sourceCodeStart":850,"sourceCodeEnd":886,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java#L850-L886","documentation":"In a batch add/update loop, after executing each child request the parser requires code=200 AND count=1. If either fails and allowPartialFailed is not enabled, a ServerException is thrown carrying key/i and the child's msg (or a note that count != 1). This is deliberate: a 200 with count != 1 would silently mask partial writes.","triggerScenarios":"Batch POST/PUT where a child row fails validation, triggers a DB constraint (duplicate key, FK violation), or the underlying exec returns count=0 or count>1 (e.g. an UPDATE matching multiple rows). allowPartialFailed is false (default), so the first failing child aborts everything.","commonSituations":"One row in a batch violates a UNIQUE constraint; STRUCTURE/REQUEST table verification rejects one child; an UPDATE without a unique id matching several rows; backend role/permission denying one child table; partial network/DB failure mid-batch.","solutions":["Read the embedded child msg in the exception — it identifies key/i and the real cause (constraint, verification, permission)","Fix the offending row's data (unique fields, required columns, valid id) and resend the batch","If some failures are acceptable, enable allowPartialFailed so the batch returns failedIdList instead of aborting","For updates matching multiple rows, restrict with a unique primary key so count is exactly 1"],"exampleFix":"// before\n{\"User:[]\":[{\"id\":1,\"name\":\"a\"},{\"id\":1,\"name\":\"dup\"}]} // duplicate id -> count!=1 or constraint error\n// after\n{\"User:[]\":[{\"id\":1,\"name\":\"a\"},{\"id\":2,\"name\":\"ok\"}]}","handlingStrategy":"try-catch","validationCode":"for (Object o : items) {\n  Map<?,?> m = (Map<?,?>) o;\n  if (m.get(idKey) == null) throw new IllegalStateException(\"missing \" + idKey);\n  // check unique fields against local state before send\n}","typeGuard":null,"tryCatchPattern":"catch (ServerException e) { if (e.getMessage().contains(\"批量新增/修改失败\")) { String idx = extract(e.getMessage(), \"(\\d+)\"); reportRow(idx, e.getMessage()); /* drop bad row, resend rest */ } else throw e; }","preventionTips":["Pre-validate unique/required fields per row client-side","Send id on every update item so count is exactly 1","Enable allowPartialFailed when partial success is acceptable and you handle failedIdList"],"tags":["apijson","batch","server-error","database","count-mismatch"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}