fix: guard add_tool_field against an orphaned tool_id - #3740
Open
AmirF194 wants to merge 1 commit into
Open
Conversation
ToolInstance.tool_id carries no foreign key, so a ToolInstance can outlive the ToolInfo row it points to. add_tool_field's query.first() then returns None, and the next line dereferences tool.params, crashing agent execution with AttributeError: 'NoneType' object has no attribute 'params'. Return None for a missing tool and skip it in search_tools_for_sub_agent's caller loop. Also default tool.params to an empty list for a tool that legitimately has none configured.
AmirF194
requested review from
Dallas98,
WMC001 and
jeffwu-1999
as code owners
August 22, 2026 07:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
ToolInstance.tool_id(backend/database/db_models.py) has no foreign key onToolInfo.tool_id, so aToolInstancerow can outlive theToolInforow itpoints to.
add_tool_fielddoes not account for that:query.first()canreturn
None, and the very next line dereferencestool.params, which isexactly the traceback in #3650:
The issue's own suggested fix,
tool_params = tool.params or [], does notfix this: the crash happens evaluating
tool.paramswhentoolitself isNone, one step before that fallback would ever run. I confirmed this byreproducing both shapes in isolation: a
Nonetool raises the reportedAttributeError, while atool.paramsofNoneraises a differentTypeErroron the iteration below it.Fix
add_tool_fieldreturnsNonewhen noToolInforow matches the giventool_id, instead of crashing.search_tools_for_sub_agent, skips aNoneresult so oneorphaned tool reference no longer aborts the whole agent run.
tool.paramsalso defaults to[], covering aToolInforow thatlegitimately has no configured params (the column is nullable), which
matches the issue title.
Verification
test/backend/database/test_tool_db.py(
test_add_tool_field_missing_tool_info_returns_none,test_add_tool_field_null_params_defaults_to_empty_list,test_search_tools_for_sub_agent_skips_orphaned_tool) fail on unmodifieddevelopwith the exact reportedAttributeErrorand pass on this branch.test/backend/databaseandtest/backend/agentssuites (1670 tests,includes
test_create_agent_info.py, which exercises the calling path)pass via
test/run_all_test.pyin the CI image (python:3.11,uv sync --extra test,uv pip install -e "../sdk[dev]").tool_db.py,no changed line in the miss list).
tool_idmissing end to end;the mock reproduces the exact code path from the traceback instead.
Fixes #3650