Skip to content

fix: preserve explicit zero-length limits in handlers and storage#440

Open
Subhajitdas99 wants to merge 4 commits intoGetBindu:mainfrom
Subhajitdas99:fix/zero-length-limit-handling
Open

fix: preserve explicit zero-length limits in handlers and storage#440
Subhajitdas99 wants to merge 4 commits intoGetBindu:mainfrom
Subhajitdas99:fix/zero-length-limit-handling

Conversation

@Subhajitdas99
Copy link
Copy Markdown
Contributor

@Subhajitdas99 Subhajitdas99 commented Apr 4, 2026

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: Explicit zero-length values like length=0 and history_length=0 were treated as falsy/missing in some handlers and storage paths.
  • Why it matters: This caused inconsistent behavior such as falling back to another parameter or returning full history/results instead of an empty result.
  • What changed: Preserved explicit zero values in handlers, returned empty history/results for zero-length requests, and aligned in-memory and PostgreSQL behavior.
  • What did NOT change (scope boundary): No protocol changes, no schema changes, no auth changes, and no new features beyond zero-limit correctness handling.

Change Type (select all that apply)

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Security hardening
  • Tests
  • Chore/infra

Scope (select all touched areas)

  • Server / API endpoints
  • Extensions (DID, x402, etc.)
  • Storage backends
  • Scheduler backends
  • Observability / monitoring
  • Authentication / authorization
  • CLI / utilities
  • Tests
  • Documentation
  • CI/CD / infra

Linked Issue/PR

  • Closes #
  • Related #

User-Visible / Behavior Changes

  • Requests with explicit length=0 now return empty results instead of being treated as missing/falsy.
  • Requests with explicit history_length=0 now return empty history consistently.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/credentials handling changed? (No)
  • New/changed network calls? (No)
  • Database schema/migration changes? (No)
  • Authentication/authorization changes? (No)
  • If any Yes, explain risk + mitigation:

Verification

Environment

  • OS: Windows
  • Python version: 3.12.9
  • Storage backend: InMemoryStorage targeted directly, PostgreSQL logic reviewed/updated
  • Scheduler backend: Mocked in handler tests

Steps to Test

  1. Run targeted unit tests for context handlers, message handlers, and memory storage.
  2. Verify length=0 is preserved in contexts/list instead of falling back to history_length.
  3. Verify history_length=0 returns empty history and zero-length list calls return empty results.

Expected Behavior

  • Explicit zero limits are preserved and interpreted as valid limits.
  • length=0 returns empty task/context results.
  • history_length=0 returns empty task history.

Actual Behavior

  • Verified the above behavior in targeted tests.
  • Targeted test result: 79 passed.

Evidence (attach at least one)

  • Failing test before + passing after
  • Test output / logs
  • Screenshot / recording
  • Performance metrics (if relevant)

Human Verification (required)

What you personally verified (not just CI):

  • Verified scenarios: Explicit length=0 in context listing, explicit history_length=0 in message scheduling and task history loading, zero-length list behavior in in-memory storage.
  • Edge cases checked: Zero-length values are not replaced by fallback parameters and do not behave like omitted values.
  • What you did NOT verify: Full repository-wide test suite and pre-commit hooks are currently blocked by unrelated existing repo issues, including the known DID __future__ import syntax problem.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Database migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert this PR/commit.
  • Files/config to restore: Handler and storage files touched in this PR.
  • Known bad symptoms reviewers should watch for: Requests with zero-length values unexpectedly returning non-empty history/results.

Risks and Mitigations

List only real risks for this PR. If none, write None.

  • Risk: Some callers may have unintentionally relied on old falsy handling of zero values.
    • Mitigation: The new behavior matches explicit parameter intent and adds regression coverage for zero-limit handling.

Checklist

  • Tests pass (uv run pytest)
  • Pre-commit hooks pass (uv run pre-commit run --all-files)
  • Documentation updated (if needed)
  • Security impact assessed
  • Human verification completed
  • Backward compatibility considered

Summary by CodeRabbit

  • Bug Fixes

    • Honor explicit zero for pagination and history parameters (returns empty results when length/history = 0).
    • Enforce strict validation: reject booleans, non-integers, and negative values for history/pagination inputs instead of silently falling back.
  • Tests

    • Added unit tests covering zero-length behavior and validation failures for listing, loading, and scheduling flows.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 13c51426-1b1a-40c1-9e61-472b36143416

📥 Commits

Reviewing files that changed from the base of the PR and between bf73535 and 968c714.

📒 Files selected for processing (1)
  • bindu/server/handlers/message_handlers.py

📝 Walkthrough

Walkthrough

Handlers now strictly validate non-negative integer length/history_length (rejecting bool, non-int, negative), preserve explicit zero values by checking key presence, and storage/listing logic treats 0 as empty (history [] or [] results). Tests added for zero and invalid inputs.

Changes

Cohort / File(s) Summary
Context Handler Parameter Logic
bindu/server/handlers/context_handlers.py
Added ContextHandlers._parse_non_negative_length(...); list_contexts prefers params["length"] when present (accepts 0) and validates non-negative integer inputs.
Message Handler Task Scheduling
bindu/server/handlers/message_handlers.py
_submit_and_schedule_task checks for presence of "history_length" and uses a new _parse_non_negative_history_length validator; forwards parsed history_length (including 0) to scheduler params.
In-Memory Storage Pagination & History
bindu/server/storage/memory_storage.py
load_task truncates history when history_length provided and sets [] for history_length == 0. list_tasks, list_tasks_by_context, and list_contexts return [] immediately when length == 0.
Postgres Storage History Truncation
bindu/server/storage/postgres_storage.py
load_task explicitly sets task["history"] = [] for history_length == 0; positive values still return last N entries, None means no truncation.
Handler Tests
tests/unit/server/handlers/test_context_handlers.py, tests/unit/server/handlers/test_message_handlers.py
Added async tests ensuring length: 0 is preserved (calls storage with 0), history_length: 0 is forwarded to scheduler, and invalid (non-int or negative) inputs raise ValueError without calling storage/scheduler.
Storage Tests
tests/unit/server/storage/test_memory_storage.py
Added tests for zero-history and zero-length behavior: load_task(..., history_length=0) yields empty history; list_tasks(length=0) and list_contexts(length=0) return [].

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Handler
    participant Scheduler
    participant Storage

    Client->>Handler: Request (params includes length/history_length)
    Handler->>Handler: _parse_non_negative_* (reject bool/non-int/neg, accept 0)
    alt submit & schedule
        Handler->>Scheduler: run_task(scheduler_params with history_length maybe 0)
        Scheduler->>Storage: create/load task
        Storage-->>Scheduler: task (history truncated if history_length provided)
    else list contexts/tasks
        Handler->>Storage: list_contexts/list_tasks(length)  -- length==0 returns []
        Storage-->>Handler: result list
    end
    Handler-->>Client: Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I checked each zero, no longer ignored,
Numbers must be whole, not boolean faux,
History trimmed to empty if asked,
Lists now honest when limits are passed,
Hop, validate, and onward I go! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: preserving explicit zero-length limits in handlers and storage, which is the core fix addressed throughout the changeset.
Description check ✅ Passed The description follows the template structure with all major sections completed: summary with problem/impact/changes, change type and scope checkboxes, user-visible behavior, comprehensive security assessment, verification environment/steps/evidence, backward compatibility confirmation, recovery instructions, and risk mitigation details. The description is thorough and well-organized.
Docstring Coverage ✅ Passed Docstring coverage is 96.67% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bindu/server/handlers/context_handlers.py`:
- Around line 46-49: The current assignment to length from params may accept
non-integer or negative values; update the logic in context_handlers.py where
length is derived from params (the length variable) to validate and normalize it
before forwarding to storage: ensure length is an int and >= 0 (accept 0),
otherwise clear/omit it (e.g., set to None) so invalid values like "", "0"
(string), or negatives are not forwarded; add a simple type-check/coercion path
only for safe numeric types if desired and add a type hint for the
params/handler signature to reflect an Optional[int] for history_length/length.

In `@bindu/server/handlers/message_handlers.py`:
- Around line 131-132: Validate and sanitize config["history_length"] before
adding it to scheduler_params: ensure the value is an integer and >= 0
(preserving 0), e.g., check isinstance(config["history_length"], int) and
config["history_length"] >= 0; if it's a numeric string you may attempt safe
coercion with int(...) inside a try/except, otherwise skip assignment or
raise/log a clear error; update the code that currently sets
scheduler_params["history_length"] from config to perform this validation and
only assign when the value is a valid non-negative int.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 77c9bf50-8518-451c-a7b3-bd4a4bd0dc97

📥 Commits

Reviewing files that changed from the base of the PR and between 45656ee and 6b83f07.

📒 Files selected for processing (7)
  • bindu/server/handlers/context_handlers.py
  • bindu/server/handlers/message_handlers.py
  • bindu/server/storage/memory_storage.py
  • bindu/server/storage/postgres_storage.py
  • tests/unit/server/handlers/test_context_handlers.py
  • tests/unit/server/handlers/test_message_handlers.py
  • tests/unit/server/storage/test_memory_storage.py

Comment on lines +46 to +49
if "length" in params:
length = params["length"]
else:
length = params.get("history_length")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate length type before forwarding to storage.

This now correctly preserves 0, but it also forwards invalid external values (e.g., "", "0", negative numbers), which can fail in storage calls.

Suggested hardening
         params = request.get("params", {})
-        if "length" in params:
-            length = params["length"]
-        else:
-            length = params.get("history_length")
+        if "length" in params:
+            length = params["length"]
+        else:
+            length = params.get("history_length")
+
+        if length is not None:
+            if not isinstance(length, int) or length < 0:
+                raise TypeError("length must be a non-negative integer or null")

As per coding guidelines: "Validate all external input and use type hints for input validation in Python files".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bindu/server/handlers/context_handlers.py` around lines 46 - 49, The current
assignment to length from params may accept non-integer or negative values;
update the logic in context_handlers.py where length is derived from params (the
length variable) to validate and normalize it before forwarding to storage:
ensure length is an int and >= 0 (accept 0), otherwise clear/omit it (e.g., set
to None) so invalid values like "", "0" (string), or negatives are not
forwarded; add a simple type-check/coercion path only for safe numeric types if
desired and add a type hint for the params/handler signature to reflect an
Optional[int] for history_length/length.

Comment thread bindu/server/handlers/message_handlers.py Outdated
@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

I also found that CI setup was failing because uv.lock was out of sync with the repo dependency metadata, so I’ve pushed a lockfile refresh.

The remaining local pre-commit/pytest failure is still caused by the existing unrelated syntax issue in bindu/extensions/did/did_agent_extension.py, not by the zero-length limit changes in this PR.

@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Good catch. I’ve updated this to validate external limit inputs before forwarding them, while still preserving explicit 0. Invalid values such as strings, booleans, and negative integers are now rejected with a clear ValueError, and I added regression coverage for those cases.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
bindu/server/handlers/message_handlers.py (1)

58-67: Consider extracting shared validation logic.

This validation method duplicates _parse_non_negative_length in context_handlers.py. A shared utility (e.g., in bindu/utils/validation.py) could reduce duplication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@bindu/server/handlers/message_handlers.py` around lines 58 - 67, Extract the
duplicated validation logic into a shared utility function (e.g.,
validate_non_negative_int) in a new module bindu/utils/validation.py and update
both _parse_non_negative_history_length (in message_handlers.py) and
_parse_non_negative_length (in context_handlers.py) to delegate to that utility;
the shared function should accept the raw value and a field name or message,
perform the same checks (None -> None, reject bool, non-int, or negative ->
raise ValueError with a clear message), and return the validated int so both
handler methods become one-line wrappers calling validate_non_negative_int.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@bindu/server/handlers/message_handlers.py`:
- Around line 142-145: The code assigns the result of
_parse_non_negative_history_length (which may return int or None) directly into
scheduler_params["history_length"], causing a type error for TaskSendParams
which expects an int; change the logic in the block that handles
config["history_length"] so you call
self._parse_non_negative_history_length(config["history_length"]) and only set
scheduler_params["history_length"] when the parsed value is not None (i.e., skip
the assignment if parsing returns None) to ensure TaskSendParams.history_length
remains an int.

---

Nitpick comments:
In `@bindu/server/handlers/message_handlers.py`:
- Around line 58-67: Extract the duplicated validation logic into a shared
utility function (e.g., validate_non_negative_int) in a new module
bindu/utils/validation.py and update both _parse_non_negative_history_length (in
message_handlers.py) and _parse_non_negative_length (in context_handlers.py) to
delegate to that utility; the shared function should accept the raw value and a
field name or message, perform the same checks (None -> None, reject bool,
non-int, or negative -> raise ValueError with a clear message), and return the
validated int so both handler methods become one-line wrappers calling
validate_non_negative_int.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0dda1381-be75-4b2f-95ab-5b61a7f52729

📥 Commits

Reviewing files that changed from the base of the PR and between 6b83f07 and bf73535.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • bindu/server/handlers/context_handlers.py
  • bindu/server/handlers/message_handlers.py
  • tests/unit/server/handlers/test_context_handlers.py
  • tests/unit/server/handlers/test_message_handlers.py
✅ Files skipped from review due to trivial changes (1)
  • tests/unit/server/handlers/test_context_handlers.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/server/handlers/test_message_handlers.py

Comment thread bindu/server/handlers/message_handlers.py
@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

I checked the failing CI log.

There was one PR-local typing issue in message_handlers.py around assigning history_length, and I’ve pushed a fix for that.

The remaining failures are still coming from unrelated repository-wide issues outside this PR, including:

  • bindu/extensions/did/did_agent_extension.py syntax error
  • invalid YAML in examples/ag2_research_team/.../skill.yaml
  • detect-secrets hits in examples/pdf_research_agent/...
  • formatting/pre-commit changes on unrelated files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant