[Bug] handle_multiple_group_ids raises TypeError: got multiple values for argument when group_ids and driver are both passed positionally with >1 group_id
Summary
handle_multiple_group_ids (graphiti_core/decorators.py)'s multi-group_id
branch rebuilds the call for each group as:
filtered_args = list(args)
if group_ids_pos is not None and len(args) > group_ids_pos:
filtered_args.pop(group_ids_pos)
return await func(
self, *filtered_args,
**{**kwargs, 'group_ids': [gid], 'driver': driver.clone(database=gid)},
)
This only removes group_ids from the positional slot it occupied in the
original call. If the caller also passed driver positionally (which is
legal — driver is a normal positional-or-keyword parameter on every
decorated method, e.g. Graphiti.build_communities(self, group_ids=None, driver=None)), the remaining positional arguments shift down by one slot
when func is re-invoked. The shifted argument then collides with a
parameter name the wrapper also injects as a kwarg (group_ids or driver,
depending on their relative order in the signature), raising a TypeError
before the wrapped method's body ever runs.
This is a different defect from #1659 (single-group_id FalkorDB routing,
already fixed on main) — it affects the multi-group_id branch and is not
covered by the existing test suite (tests/test_handle_multiple_group_ids.py
only exercises keyword-argument calls).
Type of Change
Objective
Fix handle_multiple_group_ids's multi-group_id branch to bind arguments by
name (e.g. via inspect.signature(func).bind(...) or by always passing
group_ids/driver as keyword-only within the wrapper) instead of relying
on raw positional-list surgery, so callers who pass group_ids and/or
driver positionally don't hit an argument-binding collision.
What I was trying to do
Call a handle_multiple_group_ids-decorated method with more than one
group_id, passing both group_ids and driver positionally — a pattern
the real method signatures allow since both are ordinary
positional-or-keyword parameters.
What I expected
The call to route per-group_id and merge results, the same as it does when
group_ids is passed as a keyword argument.
What actually happened
TypeError: Graphiti.build_communities() got multiple values for argument 'group_ids'
raised from inside the decorator's execute_for_group helper, before
build_communities's body runs.
Reproduction
Exercised directly against the real, unmodified Graphiti.build_communities:
from types import SimpleNamespace
from graphiti_core.driver.driver import GraphProvider
from graphiti_core.graphiti import Graphiti
class _FakeDriver:
provider = GraphProvider.FALKORDB
_database = 'reggraph'
def clone(self, database):
clone = _FakeDriver()
clone._database = database
return clone
async def main():
g = Graphiti.__new__(Graphiti) # bypass __init__; no LLM/DB needed
driver = _FakeDriver()
g.clients = SimpleNamespace(driver=driver)
g.max_coroutines = None
# Real signature: build_communities(self, group_ids=None, driver=None)
result = await g.build_communities(['a', 'b'], driver)
print('result:', result)
import asyncio; asyncio.run(main())
Actual output against main:
TypeError: Graphiti.build_communities() got multiple values for argument 'group_ids'
The TypeError occurs during argument binding inside the decorator, before
any driver I/O — no live database connection is required to demonstrate the
collision, though the finding was cross-checked against a disposable
FalkorDB-shaped fake to confirm the is_falkor / multi-group branch is what
gets exercised.
On the use of Graphiti.__new__ and a stub driver: a fully-constructed
Graphiti would require a live FalkorDB instance and a configured LLM client,
neither of which the failure depends on — the TypeError is raised while
binding arguments, before the decorated method's body runs and before any
connection is opened, so the object's remaining state is never reached. The
stub supplies only provider and clone(), which are the two attributes the
decorator itself touches on the multi-group path. Happy to provide an
equivalent reproduction against a real FalkorDB instance and LLM client if
that would be more useful for triage.
Testing
Reproduced against the real Graphiti.build_communities method (not a
stand-in). tests/test_handle_multiple_group_ids.py's existing four tests
all call the decorated function with group_ids as a keyword argument, so
none of them exercise this path. A fix should add a test calling with both
group_ids and driver positional, multiple group_ids, and assert no
TypeError.
Breaking Changes
None expected — the fix only needs to change how the wrapper re-invokes
func internally (bind-by-name instead of positional-list surgery); the
decorator's external calling contract is unchanged.
Checklist
Related Issues
Distinct from #1659 (single-group_id FalkorDB routing, already fixed on
main). No existing issue found covering this positional-argument collision
in the multi-group_id branch.
[Bug]
handle_multiple_group_idsraisesTypeError: got multiple values for argumentwhengroup_idsanddriverare both passed positionally with >1 group_idSummary
handle_multiple_group_ids(graphiti_core/decorators.py)'s multi-group_idbranch rebuilds the call for each group as:
This only removes
group_idsfrom the positional slot it occupied in theoriginal call. If the caller also passed
driverpositionally (which islegal —
driveris a normal positional-or-keyword parameter on everydecorated method, e.g.
Graphiti.build_communities(self, group_ids=None, driver=None)), the remaining positional arguments shift down by one slotwhen
funcis re-invoked. The shifted argument then collides with aparameter name the wrapper also injects as a kwarg (
group_idsordriver,depending on their relative order in the signature), raising a
TypeErrorbefore the wrapped method's body ever runs.
This is a different defect from #1659 (single-group_id FalkorDB routing,
already fixed on
main) — it affects the multi-group_id branch and is notcovered by the existing test suite (
tests/test_handle_multiple_group_ids.pyonly exercises keyword-argument calls).
Type of Change
Objective
Fix
handle_multiple_group_ids's multi-group_id branch to bind arguments byname (e.g. via
inspect.signature(func).bind(...)or by always passinggroup_ids/driveras keyword-only within the wrapper) instead of relyingon raw positional-list surgery, so callers who pass
group_idsand/ordriverpositionally don't hit an argument-binding collision.What I was trying to do
Call a
handle_multiple_group_ids-decorated method with more than onegroup_id, passing bothgroup_idsanddriverpositionally — a patternthe real method signatures allow since both are ordinary
positional-or-keyword parameters.
What I expected
The call to route per-group_id and merge results, the same as it does when
group_idsis passed as a keyword argument.What actually happened
raised from inside the decorator's
execute_for_grouphelper, beforebuild_communities's body runs.Reproduction
Exercised directly against the real, unmodified
Graphiti.build_communities:Actual output against
main:The
TypeErroroccurs during argument binding inside the decorator, beforeany driver I/O — no live database connection is required to demonstrate the
collision, though the finding was cross-checked against a disposable
FalkorDB-shaped fake to confirm the
is_falkor/ multi-group branch is whatgets exercised.
On the use of
Graphiti.__new__and a stub driver: a fully-constructedGraphitiwould require a live FalkorDB instance and a configured LLM client,neither of which the failure depends on — the
TypeErroris raised whilebinding arguments, before the decorated method's body runs and before any
connection is opened, so the object's remaining state is never reached. The
stub supplies only
providerandclone(), which are the two attributes thedecorator itself touches on the multi-group path. Happy to provide an
equivalent reproduction against a real FalkorDB instance and LLM client if
that would be more useful for triage.
Testing
Reproduced against the real
Graphiti.build_communitiesmethod (not astand-in).
tests/test_handle_multiple_group_ids.py's existing four testsall call the decorated function with
group_idsas a keyword argument, sonone of them exercise this path. A fix should add a test calling with both
group_idsanddriverpositional, multiple group_ids, and assert noTypeError.Breaking Changes
None expected — the fix only needs to change how the wrapper re-invokes
funcinternally (bind-by-name instead of positional-list surgery); thedecorator's external calling contract is unchanged.
Checklist
mainusing the realGraphiti.build_communitiessignature (not cut, per the batch's own verify-or-cut gate)
routing gap
Related Issues
Distinct from #1659 (single-group_id FalkorDB routing, already fixed on
main). No existing issue found covering this positional-argument collisionin the multi-group_id branch.