{"record":{"id":"2598e6c0bc7a9538","repo":"bytedance/deer-flow","slug":"agent-name","errorCode":null,"errorMessage":"agent_name","messagePattern":"agent_name","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py","lineNumber":925,"sourceCode":"        misreport a storage cap on backends that normalize differently.\n\n        The new fact is then trimmed by :func:`_trim_facts_to_max` (highest-\n        confidence wins, confidence coerced). If the cap evicts the just-added\n        (lower-confidence) fact, ``fact_id`` is ``None`` so callers report\n        \"not stored - cap reached\" instead of a dangling id with a false\n        \"added\" status. This restores both the max_facts cap and the post-trim\n        existence check (upstream's ``create_memory_fact_with_created_fact``),\n        which the vendored copy had dropped together to avoid the dangling id.\n\n        Duplicate rejection is enforced here (not only by callers): the\n        candidate's normalized content key is checked against the fresh\n        memory snapshot inside the revision-conflict retry loop of both\n        storage paths (apply_changes and legacy single-file save), so\n        concurrent creators cannot both store the same content. Raises\n        ``ValueError(\"Duplicate fact\")`` on a normalized-content match.\n        \"\"\"\n        if agent_name is None:\n            raise ValueError(\"agent_name\")\n        normalized_content = content.strip()\n        if not normalized_content:\n            raise ValueError(\"content\")\n        normalized_category = category.strip() or \"context\"\n        validated_confidence = _validate_confidence(confidence)\n        candidate_key = _fact_content_key(normalized_content)\n        now = utc_now_iso_z()\n        fact_id = f\"fact_{uuid.uuid4().hex[:8]}\"\n        candidate = {\n            \"id\": fact_id,\n            \"content\": normalized_content,\n            \"category\": normalized_category,\n            \"confidence\": validated_confidence,\n            \"createdAt\": now,\n            \"source\": \"manual\",\n        }\n        if getattr(type(self._storage), \"apply_changes\", None) is not MemoryStorage.apply_changes:\n            for attempt in range(3):","sourceCodeStart":907,"sourceCodeEnd":943,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py#L907-L943","documentation":"create_memory_fact requires an explicit agent_name; passing None (the default) raises ValueError('agent_name') immediately. DeerMem stores facts in per-agent buckets even on shared backends, so the code refuses to guess a bucket.","triggerScenarios":"Calling create_memory_fact(content, category, confidence) without the positional agent_name argument, or passing agent_name=None explicitly (e.g. forwarding an optional CLI/tool parameter that was never filled in).","commonSituations":"A wrapper tool exposes an optional agent parameter and forwards it verbatim; migrations from an older API where agent_name was not required; tests that call the factory method with default args.","solutions":["Pass a concrete agent_name, e.g. create_memory_fact('likes tea', 'context', 0.8, 'researcher')","If wrapping the call, default the missing parameter at your boundary: agent_name or DEFAULT_AGENT","Fail fast at your API surface with a 400 instead of letting ValueError escape as a 500"],"exampleFix":"// before\nmemory.create_memory_fact(content=\"likes tea\", category=\"context\")\n// after\nmemory.create_memory_fact(content=\"likes tea\", category=\"context\", agent_name=\"researcher\")","handlingStrategy":"validation","validationCode":"if not agent_name:\n    raise HTTPException(400, \"agent_name is required\")\n_, fact_id = memory.create_memory_fact(content, agent_name=agent_name)","typeGuard":"def has_agent(agent: str | None) -> TypeGuard[str]:\n    return isinstance(agent, str) and bool(agent)","tryCatchPattern":"try:\n    memory.create_memory_fact(content, agent_name=agent)\nexcept ValueError as e:\n    if str(e) == \"agent_name\":\n        raise HTTPException(400, \"agent_name is required\")\n    raise","preventionTips":["Make agent_name a required field in every tool/HTTP schema that reaches memory writes","Unit-test the missing-agent_name path so the 400 mapping stays in place"],"tags":["memory","deermem","validation","required-argument"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}