Skip to content

[Bug]: _clean_empty silently drops legitimate falsy values (0, False, 0.0) #692

Closed

Description

@cchinchilla-dev

What happened?

_clean_empty in src/a2a/utils/helpers.py is documented to "recursively remove empty strings, lists and dicts". The base case correctly targets only '', [], {}, but the dict and list filters use truthiness (if v) which also drops 0, False, and 0.0:

return {k: v for k, v in cleaned_dict.items() if v}    # drops 0, False, 0.0
return [v for v in cleaned_list if v]                   # drops 0, False, 0.0
return d if d not in ['', [], {}] else None             # correct

This affects canonicalize_agent_card() (the only caller), which produces canonical JSON for signature verification (RFC 8785). An AgentCard with e.g. AgentCapabilities(streaming=False) would have the field stripped after surviving model_dump(exclude_none=True), losing the distinction between "explicitly disabled" and "unspecified".

Reproduction:

from a2a.utils.helpers import _clean_empty

assert _clean_empty({"retries": 0}) == {}        # expected: {"retries": 0}
assert _clean_empty({"enabled": False}) == {}     # expected: {"enabled": False}
assert _clean_empty([0, 1, 2]) == [1, 2]          # expected: [0, 1, 2]

Suggested fix — align filters with the base case:

return {k: v for k, v in cleaned_dict.items() if v is not None}
return [v for v in cleaned_list if v is not None]

If this behavior is intentional, I may be missing some context — in that case, clarifying the docstring and base case to better reflect the current filtering semantics could help avoid confusion.

If it’s considered a bug, I’d be glad to open a PR with the proposed change and add regression tests as needed.

Relevant log output

No output — values are dropped silently.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Activity

  1. self-assigned this
    on Feb 18, 2026
  2. rohityan commented on Feb 19, 2026

    @rohityan

    Hi @cchinchilla-dev , thanks for bringing this up.
    _clean_empty function is designed to eliminate empty strings, lists and dictionaries.
    Your solution if v is not None would preserve values like 0, False, 0.0 ,however it will deviate from the function purpose of removing empty strings, lists and dictionaries.
    Please go ahead a propose a PR for this but your solution needs to be adapted to the above case.

  3. added
    component: coreIssues related to base data models, auth, gRPC interfaces, observability, and fundamental utilities.
    on Feb 19, 2026
  4. cchinchilla-dev commented on Feb 19, 2026

    @cchinchilla-dev
    ContributorAuthor

    Hi @ryanaiagent,

    Thanks for the review! You're right — if v is not None would let [] and {} slip through since they never reach the base case. I'll open a PR shortly using explicit sentinel checks instead, with tests covering both sides.

  5. added a commit that references this issue on Feb 20, 2026
    7632f55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

component: coreIssues related to base data models, auth, gRPC interfaces, observability, and fundamental utilities.

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions