{"record":{"id":"1aab6511f3f13f66","repo":"Tencent/APIJSON","slug":"put-1aab65","errorCode":null,"errorMessage":"PUT {}, {}/{} 不存在！","messagePattern":"PUT (.+?), (.+?)/(.+?) 不存在！","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java","lineNumber":766,"sourceCode":"\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (isAdd) {\n\t\t\t\tif (targetArray != null) {\n\t\t\t\t\tif (targetArray.contains(obj)) {\n\t\t\t\t\t\tthrow new ConflictException(\"PUT \" + path + \", \" + key + \"/\" + i + \" 已存在！\");\n\t\t\t\t\t}\n\t\t\t\t\ttargetArray.add(obj);\n\t\t\t\t} else {\n\t\t\t\t\tif (obj != null && obj instanceof Map == false) {\n\t\t\t\t\t\tthrow new ConflictException(\"PUT \" + path + \", \" + key + \"/\" + i + \" 必须为 JSONRequest {} ！\");\n\t\t\t\t\t}\n\t\t\t\t\ttargetObj.putAll((Map) obj);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (targetArray != null) {\n\t\t\t\t\tif (targetArray.contains(obj) == false) {\n\t\t\t\t\t\tthrow new NullPointerException(\"PUT \" + path + \", \" + key + \"/\" + i + \" 不存在！\");\n\t\t\t\t\t}\n\t\t\t\t\ttargetArray.remove(obj);\n\t\t\t\t} else {\n\t\t\t\t\tif (obj instanceof String == false) {\n\t\t\t\t\t\tthrow new ConflictException(\"PUT \" + path + \", \" + key + \"/\" + i + \" 必须为 String 类型 ！\");\n\t\t\t\t\t}\n\t\t\t\t\tif (targetObj.containsKey(obj) == false) {\n\t\t\t\t\t\tthrow new NullPointerException(\"PUT \" + path + \", \" + key + \"/\" + i + \" 不存在！\");\n\t\t\t\t\t}\n\t\t\t\t\ttargetObj.remove(obj);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//add all 或 remove all >>>>>>>>>>>>>>>>>>>>>>>>>\n\n\t\t//PUT <<<<<<<<<<<<<<<<<<<<<<<<<\n\t\tsqlRequest.put(realKey, targetArray != null ? targetArray : JSON.toJSONString(targetObj)); // FIXME, SerializerFeature.WriteMapNullValue));","sourceCodeStart":748,"sourceCodeEnd":784,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractObjectParser.java#L748-L784","documentation":"Mirror of the conflict check for 'key-': when removing from a JSONArray-valued column, each element must already exist (targetArray.contains(obj)); otherwise NullPointerException '不存在！' is thrown with the key and index. Removal of a non-existent element is treated as a client error rather than a silent no-op.","triggerScenarios":"PUT { \"tags-\": [\"music\"] } where tags currently is [\"sport\"] — \"music\" is not in the array, so the removal aborts.","commonSituations":"Stale client state (UI shows a tag the server already removed); concurrent removals racing each other; retrying an already-applied removal.","solutions":["Client-side: only send elements confirmed present in the freshest fetched value.","Catch NullPointerException on key- and re-fetch the row when stale state is suspected (optimistic-concurrency style).","Serialize concurrent edits of the same JSON column to avoid racing removals."],"exampleFix":"// before\nremove(\"music\"); // server tags = [\"sport\"] -> error\n// after\nList<String> del = wanted.stream().filter(currentTags::contains).collect(toList());\nif (!del.isEmpty()) removeViaKeyMinus(del);","handlingStrategy":"try-catch","validationCode":"JSONArray current = fetchArrayColumn(tableName, id, key);\nJSONArray toRemove = new JSONArray();\nfor (Object o : payload) if (current.contains(o)) toRemove.add(o); // only existing items\nif (!toRemove.isEmpty()) sendKeyMinus(key, toRemove);","typeGuard":"function filterPresent<T>(current: T[], remove: T[]): T[] {\n  return remove.filter(x => current.some(c => JSON.stringify(c) === JSON.stringify(x)));\n}","tryCatchPattern":"try { sendKeyMinus(...); } catch (NullPointerException e) { if (String.valueOf(e.getMessage()).contains(\"不存在\")) { refetchRow(); // stale client state; reconcile and optionally retry } else throw e; }","preventionTips":["Refetch the row before composing key- payloads.","Only send elements confirmed present in the latest value.","Handle '不存在' as an optimistic-concurrency signal: re-fetch and reconcile."],"tags":["apijson","put","not-found","json-array","stale-state"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}