Skip to content

Conversation

@Yo-sure
Copy link
Contributor

@Yo-sure Yo-sure commented Nov 22, 2025

Problem

CompositeBackend has a path truncation bug when route prefixes are registered without a trailing slash. The bug occurs in the ls_info method at line 79:

fi["path"] = f"{route_prefix[:-1]}{fi['path']}"

This code assumes route prefixes always end with /, but the constructor accepts prefixes without trailing slashes. This causes path truncation:

Bug Example:

backend = CompositeBackend(
    default=fs,
    routes={"/workspace": workspace_backend}  # No trailing slash
)

# Bug: route_prefix[:-1] truncates the last character
# "/workspace"[:-1] = "/workspac"  ❌
# Result: /workspac/file.txt instead of /workspace/file.txt

Expected Behavior:

# "/workspace/"[:-1] = "/workspace"  ✅
# Result: /workspace/file.txt

Root Cause

The ls_info method (and grep_raw, glob_info) rely on route_prefix[:-1] to strip the trailing slash when constructing paths. However, the constructor does not enforce or normalize route prefixes to end with /, leading to inconsistent behavior.

Solution

Normalize all route prefixes to end with / in the __init__ method:

# Normalize route prefixes to end with / (e.g., "/workspace" → "/workspace/")
normalized_routes = {}
for route_prefix, backend in routes.items():
    normalized_prefix = route_prefix if route_prefix.endswith("/") else route_prefix + "/"
    normalized_routes[normalized_prefix] = backend

This ensures:

  1. Consistency: All routes are stored in a normalized format internally
  2. Backwards compatibility: Both /workspace and /workspace/ work correctly
  3. Correctness: route_prefix[:-1] logic works as designed

Testing

Reproduction

Created test_composite_bug2.py to reproduce the bug:

# Test WITHOUT trailing slash (before fix)
backend = CompositeBackend(
    default=fs,
    routes={"/workspace": workspace_backend}  # No trailing slash
)
results = backend.ls_info("/workspace")
# Bug: ["/workspac/file1.txt", "/workspac/file2.txt"]  ❌

Result after fix:

✅ ["/workspace/file1.txt", "/workspace/file2.txt"]

Verification

  • Existing unit tests pass (Windows path separators are a known issue, unrelated to this fix)
  • Both /workspace and /workspace/ route formats work correctly
  • No breaking changes to public API

Changes

  • libs/deepagents/deepagents/backends/composite.py
    • Added route prefix normalization in __init__
    • Added class and method docstrings per contributing guidelines
    • Maintains backwards compatibility

Impact

  • Users affected: Anyone using CompositeBackend with routes not ending in /
  • Severity: Medium (causes incorrect file paths in ls/glob/grep operations)
  • Breaking changes: None (pure bugfix)

…tion

- Route prefixes are now automatically normalized to end with /
- Prevents path truncation when route_prefix[:-1] is used in ls_info
- Example: '/workspace' is normalized to '/workspace/' on initialization
- Maintains backwards compatibility: both formats work correctly
@eyurtsev eyurtsev self-assigned this Nov 22, 2025
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.

2 participants