Tencent/APIJSON · error · ServerException

批量新增/修改 {}:{} 中 {} 个子项全部失败!第 {} 项失败原因:{}

Error message

批量新增/修改 {}:{} 中 {} 个子项全部失败!第 {} 项失败原因:{}

What it means

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.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java:881

                    if (firstFailIndex < 0) {
                        firstFailIndex = i;
                    }
                }
                else {
                    throw new ServerException(
                            "批量新增/修改失败!" + key + "/" + i + ":" + (success ? "成功但 count != 1 !"
                                    : (result == null ? "null" : getString(result, JSONResponse.KEY_MSG))
                    ));
                }
            }

			allCount += 1; // 加了 allowPartialFailed 后 count 可能为 0  allCount += count;
			ids.add(id);
		}

        int failedCount = failedIds == null ? 0 : failedIds.size();
        if (failedCount > 0 && failedCount >= allCount) {
            throw new ServerException("批量新增/修改 " + key + ":[] 中 " + allCount + " 个子项全部失败!"
                    + "第 " + firstFailIndex + " 项失败原因:" + (firstFailThrow == null ? "" : firstFailThrow.getMessage()));
        }

        M allResult = getParser().newSuccessResult();
        if (failedCount > 0) {
            allResult.put("failedCount", failedCount);
            allResult.put("failedIdList", failedIds);

            M failObj = JSON.createJSONObject();
            failObj.put("index", firstFailIndex);
            failObj.put(childKey, firstFailReq);

            if (firstFailThrow instanceof CommonException && firstFailThrow.getCause() != null) {
                firstFailThrow = firstFailThrow.getCause();
            }
            M obj = firstFailThrow == null ? failObj : getParser().extendErrorResult(failObj, firstFailThrow, parser.isRoot());
            if (Log.DEBUG && firstFailThrow != null) {
                obj.put("trace:throw", firstFailThrow.getClass().getName());

View on GitHub (pinned to 5284052872)

Solutions

  1. Fix the first-failure cause shown in the message — it applies to all rows
  2. Check global preconditions before sending: table exists, role has access, all required fields present in every item
  3. If mixed success is expected, ensure at least one child can legitimately succeed; otherwise drop allowPartialFailed and handle the immediate error instead
  4. Retry after transient DB issues only if the first failure reason is connectivity-related

Example fix

// before: every item missing required column -> all fail
{"Comment:[]":[{"content":"a"},{"content":"b"}],"allowPartialFailed":true}
// after
{"Comment:[]":[{"momentId":1,"content":"a"},{"momentId":1,"content":"b"}],"allowPartialFailed":true}
Defensive patterns

Strategy: validation

Validate before calling

if (items.stream().allMatch(it -> !rowLooksValid(it))) { throw new IllegalStateException("batch would fail entirely: " + firstReason(items)); }

Try / catch

catch (ServerException e) { if (e.getMessage().contains("个子项全部失败")) { String firstIdx = extract(e.getMessage(), "第 (\d+) 项"); fixRootCause(firstIdx); } else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14). Data as JSON: /api/errors/5bd163dab9019384. Report an issue: GitHub.