{"record":{"id":"78246b0f08a57c55","repo":"iflytek/astron-agent","slug":"version-already-exists","errorCode":null,"errorMessage":"Version already exists!","messagePattern":"Version already exists!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"core/plugin/link/infra/tool_crud/process.py","lineNumber":146,"sourceCode":"        description: Add tool version\n        \"\"\"\n        with session_getter(self.engine) as session:\n            for tool in tool_info:\n                try:\n                    tool_inst = Tools(\n                        app_id=tool.get(\"app_id\"),\n                        tool_id=tool.get(\"tool_id\"),\n                        name=tool.get(\"name\"),\n                        description=tool.get(\"description\"),\n                        open_api_schema=tool.get(\"open_api_schema\"),\n                        version=tool.get(\"version\", const.DEF_VER),\n                        is_deleted=tool.get(\"is_deleted\", const.DEF_DEL),\n                    )\n                    session.add(tool_inst)\n                    session.commit()\n                except IntegrityError as e:\n                    session.rollback()\n                    raise Exception(\"Version already exists!\") from e\n\n    def delete_tools(self, tool_info: List[Dict[str, Any]]) -> None:\n        \"\"\"\n        description: Delete tools\n        \"\"\"\n        with session_getter(self.engine) as session:\n            for tool in tool_info:\n                tool_id = tool.get(\"tool_id\", \"\")\n                version = (tool.get(\"version\", \"\"),)\n                if isinstance(version, tuple):\n                    # If it's a tuple, take the first element\n                    version = version[0]\n\n                is_deleted = tool.get(\"is_deleted\", const.DEF_DEL)\n                if version:\n                    query = (\n                        select(Tools)\n                        .where(","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/plugin/link/infra/tool_crud/process.py#L128-L164","documentation":"add_tool_version inserts a new Tools row whose unique constraint covers (tool_id, version). When a row with the same tool_id and version already exists, the database driver raises IntegrityError on commit; the code rolls back and re-raises a plain Exception with 'Version already exists!'. It means you are trying to register a version that is already registered.","triggerScenarios":"Calling add_tool_version with a dict whose (tool_id, version) pair already exists in the tools table — e.g. omitting 'version' so it defaults to const.DEF_VER when a default-version row already exists, or re-submitting the same tool registration twice.","commonSituations":"Idempotency mistakes: retrying a registration after a timeout, omitting the version field so it collides with the default version, or a concurrent writer inserting the same version first.","solutions":["Pick a new, unique version string before calling add_tool_version","Check existence first (get_tools with the same tool_id/version) and skip or update instead of inserting","Catch this Exception and treat it as a duplicate if duplicate inserts are expected in your flow","Remove the conflicting row (delete_tools) if the old version should be replaced"],"exampleFix":"# before\nprocess.add_tool_version([{\"tool_id\": tid, \"app_id\": aid, \"name\": n}])  # defaults to DEF_VER, collides\n# after\nversion = \"1.0.1\"\nif not process.get_tools([{\"tool_id\": tid, \"version\": version}], span):\n    process.add_tool_version([{\"tool_id\": tid, \"app_id\": aid, \"name\": n, \"version\": version}])","handlingStrategy":"try-catch","validationCode":"existing = process.get_tools([{\"tool_id\": tid, \"version\": ver}], span)\nif existing:\n    process.update_tools([{...}])  # update instead of insert\nelse:\n    process.add_tool_version([{...}])","typeGuard":"def is_new_version(tool: dict, existing_versions: set) -> bool:\n    return tool.get(\"version\", const.DEF_VER) not in existing_versions","tryCatchPattern":"try:\n    process.add_tool_version(tools)\nexcept Exception as e:\n    if \"Version already exists\" in str(e):\n        logger.warning(f\"duplicate version, skipping: {tools}\")\n    else:\n        raise","preventionTips":["Always pass an explicit unique version; do not rely on the default const.DEF_VER","Make registration idempotent: check-then-insert or catch duplicates","Serialize concurrent registrations of the same tool_id"],"tags":["database","integrity-error","duplicate-record","sqlmodel"],"backgroundTag":"file-already-exists","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}