{"record":{"id":"990f6c692f987084","repo":"TencentCloud/TencentDB-Agent-Memory","slug":"field-accepts-at-most-max-items-items-got-le","errorCode":null,"errorMessage":"{field} accepts at most {max_items} items, got {len(deduped)}","messagePattern":"(.+?) accepts at most (.+?) items, got (.+?)","errorType":"validation","errorClass":"ParamError","httpStatus":null,"severity":"error","filePath":"sdk/memory-core/python/tencentdb_agent_memory/v3/client.py","lineNumber":77,"sourceCode":"    破坏性操作的入参在客户端就拦一道，比等服务端回 400 更早暴露问题，\n    也避免把明显不合法的批量请求发出去。\n\n    :returns: 归一化后的列表；``raw`` 为 None 时返回 None（表示\"未提供\"）。\n    \"\"\"\n    if raw is None:\n        return None\n    if not isinstance(raw, (list, tuple)):\n        raise ParamError(f\"{field} must be a list of non-empty strings\")\n    if any(not isinstance(item, str) or not item.strip() for item in raw):\n        raise ParamError(f\"{field} must contain only non-empty strings\")\n\n    seen: Dict[str, None] = {}\n    for item in raw:\n        seen.setdefault(item.strip(), None)\n    deduped = list(seen.keys())\n\n    if len(deduped) > max_items:\n        raise ParamError(f\"{field} accepts at most {max_items} items, got {len(deduped)}\")\n    return deduped\n\n\ndef _validate_construction(team_id: str, agent_id: str, user_id: str) -> None:\n    \"\"\"v3 构造时 team+agent+user 必填，任一缺失立刻 ParamError，避免 422 才暴露。\n\n    session_id 不在构造时强校验（L2/L3 接口不需要）；L0/L1 方法调用时再单独校验。\n    \"\"\"\n    missing = [\n        name for name, val in (\n            (\"team_id\", team_id),\n            (\"agent_id\", agent_id),\n            (\"user_id\", user_id),\n        ) if not val\n    ]\n    if missing:\n        raise ParamError(\n            f\"v3 MemoryClient requires non-empty {', '.join(missing)} at construction time\"","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/3efcd317b84146d6a08518ac0f7ee7c8a8d200ec/sdk/memory-core/python/tencentdb_agent_memory/v3/client.py#L59-L95","documentation":"After stripping whitespace and deduplicating, _normalize_delete_ids enforces the server batch-size cap (5000 for message/atomic ids, 100 for session_ids/memory_ids). Exceeding it raises ParamError before any network call, protecting the caller from a server-side batch rejection.","triggerScenarios":"delete_conversation with >5000 deduped message_ids or >100 session_ids; delete_atomic with >5000 ids; clear_chat_memory with >100 memory_ids. Duplicates are removed first, so only unique stripped values count.","commonSituations":"Bulk cleanup scripts iterating an entire conversation history at once; migrating data between environments with unbounded id lists; replaying a queue of deletion jobs into a single call instead of batching.","solutions":["Chunk the list into batches within the cap (5000 or 100) and call the API per chunk","Deduplicate and strip first so near-cap lists may drop under the limit","For clear_chat_memory, prioritize the 100 most important memory_ids per call","Check len(set(s.strip() for s in ids)) before calling"],"exampleFix":"// before\nclient.delete_atomic(ids=all_ids)  # all_ids has 8000 entries\n// after\nfor chunk in [all_ids[i:i+5000] for i in range(0, len(all_ids), 5000)]:\n    client.delete_atomic(ids=chunk)","handlingStrategy":"validation","validationCode":"MAX = 5000\nunique = {s.strip() for s in ids if isinstance(s, str) and s.strip()}\nif len(unique) > MAX:\n    raise ValueError(f\"{len(unique)} ids exceeds {MAX}\")","typeGuard":null,"tryCatchPattern":"try:\n    client.delete_atomic(ids=ids)\nexcept ParamError as e:\n    if \"accepts at most\" in str(e):\n        for chunk in batched(ids, 5000):\n            client.delete_atomic(ids=chunk)","preventionTips":["Chunk all bulk operations at 5000 (or 100 for session/memory ids) by default","Deduplicate before batching to reduce batch count","Write a batched() utility and use it for every delete call","Log list lengths before large deletes"],"tags":["python","validation","batch-limit"],"backgroundTag":"batch-size-limit-exceeded","analyzedSha":"3efcd317b84146d6a08518ac0f7ee7c8a8d200ec","analyzedAt":"2026-09-01T05:44:22.276Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}