{"record":{"id":"5bd163dab9019384","repo":"Tencent/APIJSON","slug":"error-5bd163","errorCode":null,"errorMessage":"批量新增/修改 {}:{} 中 {} 个子项全部失败！第 {} 项失败原因：{}","messagePattern":"批量新增/修改 (.+?):(.+?) 中 (.+?) 个子项全部失败！第 (.+?) 项失败原因：(.+?)","errorType":"exception","errorClass":"ServerException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java","lineNumber":881,"sourceCode":"                    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) {\n            allResult.put(\"failedCount\", failedCount);\n            allResult.put(\"failedIdList\", failedIds);\n\n            M failObj = JSON.createJSONObject();\n            failObj.put(\"index\", firstFailIndex);\n            failObj.put(childKey, firstFailReq);\n\n            if (firstFailThrow instanceof CommonException && firstFailThrow.getCause() != null) {\n                firstFailThrow = firstFailThrow.getCause();\n            }\n            M obj = firstFailThrow == null ? failObj : getParser().extendErrorResult(failObj, firstFailThrow, parser.isRoot());\n            if (Log.DEBUG && firstFailThrow != null) {\n                obj.put(\"trace:throw\", firstFailThrow.getClass().getName());","sourceCodeStart":863,"sourceCodeEnd":899,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java#L863-L899","documentation":"When allowPartialFailed is enabled, each failing child records its id/index instead of throwing. After the loop, if failedCount >= allCount (every child failed), a ServerException is still thrown: partial-failure tolerance does not extend to total failure. The message names the batch key, total count, first failing index, and its reason.","triggerScenarios":"Batch POST/PUT with allowPartialFailed=true where 100% of the child operations fail — e.g. all rows violate the same constraint, the whole request lacks permission, or the DB is down for the duration of the batch.","commonSituations":"Global cause shared by all rows: missing required column in every item, wrong table name, role denied on the child table, DB connectivity failure, schema migration removed a column referenced by every item.","solutions":["Fix the first-failure cause shown in the message — it applies to all rows","Check global preconditions before sending: table exists, role has access, all required fields present in every item","If mixed success is expected, ensure at least one child can legitimately succeed; otherwise drop allowPartialFailed and handle the immediate error instead","Retry after transient DB issues only if the first failure reason is connectivity-related"],"exampleFix":"// before: every item missing required column -> all fail\n{\"Comment:[]\":[{\"content\":\"a\"},{\"content\":\"b\"}],\"allowPartialFailed\":true}\n// after\n{\"Comment:[]\":[{\"momentId\":1,\"content\":\"a\"},{\"momentId\":1,\"content\":\"b\"}],\"allowPartialFailed\":true}","handlingStrategy":"validation","validationCode":"if (items.stream().allMatch(it -> !rowLooksValid(it))) { throw new IllegalStateException(\"batch would fail entirely: \" + firstReason(items)); }","typeGuard":null,"tryCatchPattern":"catch (ServerException e) { if (e.getMessage().contains(\"个子项全部失败\")) { String firstIdx = extract(e.getMessage(), \"第 (\\d+) 项\"); fixRootCause(firstIdx); } else throw e; }","preventionTips":["Test one item alone before sending the whole batch — total failure usually shares one root cause","Validate required columns and permissions for the child table once, not per row","Don't use allowPartialFailed as a mask for systemic data errors"],"tags":["apijson","batch","partial-failure","server-error"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}