Skip to content

[BUG]: Deleting A2A agent fails with FOREIGN KEY constraint on server_tool_association #4261

@madhav165

Description

@madhav165

🐞 Bug Summary

Deleting an A2A agent (or its associated tool) from the Admin UI fails with sqlite3.IntegrityError: FOREIGN KEY constraint failed because the server_tool_association rows referencing the tool are not cleaned up before the tool row is deleted.


🧩 Affected Component

  • mcpgateway - API
  • mcpgateway - UI (admin panel)

🔁 Steps to Reproduce

  1. Register an A2A agent (which auto-creates a corresponding tool and may associate it with a virtual server)
  2. Attempt to delete the A2A agent from the Admin UI A2A agents list
  3. Alternatively, attempt to delete the associated tool from the Admin UI tools list

Both paths fail with the same FK constraint error.


🤔 Expected Behavior

The A2A agent and its associated tool should be deleted successfully, with all dependent rows in server_tool_association cleaned up first.


📓 Logs / Error Output

ERROR [mcpgateway.services.structured_logger] [tool_service] Tool deletion failed
ERROR [mcpgateway.admin] Error deleting A2A agent: Failed to delete tool: (sqlite3.IntegrityError) FOREIGN KEY constraint failed
[SQL: DELETE FROM tools WHERE tools.id = ?]
[parameters: ('f9cb07ad1b29483ca06c25ad61d7d4b5',)]
(Background on this error at: https://sqlalche.me/e/20/gkpj)

🧠 Environment Info

Key Value
Runtime Python 3.11+
Database SQLite

🧩 Additional Context (optional)

Root cause: ToolService.delete_tool() in tool_service.py uses a Core SQL DELETE statement (delete(DbTool).where(...)) which bypasses SQLAlchemy ORM cascade rules. The server_tool_association table has a FK to tools.id with no ondelete cascade at the DB level, so the delete is rejected by SQLite's FK enforcement.

Other FK references to tools.id are fine:

  • tool_metrics — explicitly purged before deletion, and has ORM cascade="all, delete-orphan"
  • tool_metrics_hourly — has ondelete="SET NULL" at DB level
  • a2a_agents.tool_id — has ondelete="SET NULL" at DB level

Fix: delete_tool() must delete server_tool_association rows for the tool before executing the tool DELETE. The gateway service already uses this pattern (e.g., gateway_service.py:1605).

Metadata

Metadata

Assignees

Labels

apiREST API Related itembugSomething isn't workingtriageIssues / Features awaiting triageuiUser Interface

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions