iflytek/astron-agent · error · ToolNotExistsException

ErrCode.TOOL_NOT_EXIST_ERR

ErrCode.TOOL_NOT_EXIST_ERR

Error message

tools don't exist!

What it means

Raised by update_tools in the link plugin's tool CRUD layer when no Tools row matches the given tool_id/version/is_deleted combination. The SELECT finds nothing, so the update has no target row; instead of silently doing nothing, the code raises ToolNotExistsException carrying ErrCode.TOOL_NOT_EXIST_ERR. It signals that the tool you asked to update is not present (or is soft-deleted) in the tools table.

Solutions

  1. Verify the tool_id/version exists by calling get_tools with the same tool_id/version before updating
  2. Check that the version value exactly matches what add_tool_version stored (including the default const.DEF_VER)
  3. Check the is_deleted flag matches the row's soft-delete value; use delete-aware lookup or re-register the tool
  4. Insert the tool first via add_tool_version if it genuinely does not exist

Example fix

# before
process.update_tools([{"tool_id": "bad-id", "version": "v2", "name": "x"}])  # raises
# after
existing = process.get_tools([{"tool_id": "bad-id", "version": "v2"}], span)
if not existing:
    process.add_tool_version([{"tool_id": "bad-id", "version": "v2", "app_id": app_id, "name": "x"}])
else:
    process.update_tools([{"tool_id": "bad-id", "version": "v2", "name": "x"}])
Defensive patterns

Strategy: validation

Validate before calling

def tool_exists(process, tool_id, version, span):
    return bool(process.get_tools([{"tool_id": tool_id, "version": version}], span))

if not tool_exists(process, tid, ver, span):
    raise ValueError(f"tool {tid}@{ver} not registered")
process.update_tools([{...}])

Type guard

def is_valid_tool_update(d: dict) -> bool:
    return bool(d.get("tool_id")) and bool(d.get("version"))

Try / catch

try:
    process.update_tools(tools)
except ToolNotExistsException as e:
    logger.error(f"update target missing: {e.err}")
    raise HTTPException(status_code=404, detail="tool not found") from e

Prevention

When it happens

Trigger: Calling update_tools with a dict whose tool_id has no row in the tools table, whose version does not match an existing row (note version defaults to const.DEF_VER and is compared as a tuple in the WHERE clause), or whose is_deleted timestamp flag does not match the stored soft-delete value.

Common situations: Updating a tool that was already deleted (is_deleted mismatch), passing a version string that differs from the stored one (e.g. 'v1' vs '1'), a typo'd or stale tool_id from a client, or the tool was never registered before an update was attempted.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/a6c4a5544733b8ca. Report an issue: GitHub.

Appendix: source

Thrown at core/plugin/link/infra/tool_crud/process.py:111

        description: Update tools
        """
        with session_getter(self.engine) as session:
            for tool in tool_info:
                tool_id = tool.get("tool_id")
                version = (tool.get("version", const.DEF_VER),)
                is_deleted = tool.get("is_deleted", const.DEF_DEL)
                query = (
                    select(Tools)
                    .where(
                        Tools.tool_id == tool_id,
                        Tools.version == version,
                        Tools.is_deleted == is_deleted,
                    )
                    .order_by(desc(Tools.update_at))
                )
                tool_inst = session.exec(query).first()
                if tool_inst is None:
                    raise ToolNotExistsException(
                        code=ErrCode.TOOL_NOT_EXIST_ERR.code,
                        err_pre=ErrCode.TOOL_NOT_EXIST_ERR.msg,
                        err="tools don't exist!",
                    )

                if tool.get("name"):
                    tool_inst.name = tool.get("name")
                if tool.get("description"):
                    tool_inst.description = tool.get("description")
                if tool.get("open_api_schema"):
                    tool_inst.open_api_schema = tool.get("open_api_schema")
                session.add(tool_inst)
                session.commit()

    def add_tool_version(self, tool_info: List[Dict[str, Any]]) -> None:
        """
        description: Add tool version
        """

View on GitHub (pinned to 5e758547a8)