fix: reject chunk_overlap >= chunk_size in knowledge sources instead of crashing/dropping content#6552
Conversation
…of crashing/dropping content
BaseKnowledgeSource._chunk_text() (and 6 identical copies of it duplicated
across string/json/pdf/text_file/csv/excel KnowledgeSource subclasses)
compute the slicing step as chunk_size - chunk_overlap with no validation:
range(0, len(text), chunk_size - chunk_overlap)
chunk_overlap == chunk_size -> step is 0 -> ValueError("range() arg 3 must
not be zero"), a confusing error unrelated to the actual misconfiguration.
chunk_overlap > chunk_size -> step is negative -> range(0, len(text), neg)
with start(0) < stop(len(text)) silently yields nothing -> _chunk_text
returns [] -> the source's entire content is dropped with no error, no
warning, nothing indexed.
Verified both independently with a real (non-mocked) StringKnowledgeSource
instance before this fix: chunk_overlap=chunk_size raises the confusing
range() ValueError; chunk_overlap>chunk_size raises nothing and silently
produces zero chunks.
Fix: add a single `@model_validator(mode="after")` on BaseKnowledgeSource
that rejects chunk_overlap >= chunk_size at construction time with a clear
message. Since every one of the 7 duplicated _chunk_text implementations
reads self.chunk_size/self.chunk_overlap from the same inherited Pydantic
fields, and Pydantic validators are inherited by subclasses, this one
change protects all 7 call sites without needing to touch each file's
duplicated _chunk_text individually. Confirmed via direct instantiation of
StringKnowledgeSource with the bad configs both now raise ValidationError
at construction time, before any chunking is ever attempted.
Added tests/knowledge/test_base_knowledge_source_chunk_overlap.py: equal
values rejected, overlap > size rejected, a valid overlap < size accepted,
and the library's own defaults (chunk_size=4000, chunk_overlap=200) pass
the new check. Confirmed red->green (reverting the source change reproduces
"DID NOT RAISE ValueError" for both bad-config tests). Full
tests/knowledge/ suite: 58 passed, no regressions. ruff + mypy clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughChangesChunk overlap validation
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
lib/crewai/src/crewai/knowledge/source/base_knowledge_source.py (1)
32-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider adding bounds validation for
chunk_sizeandchunk_overlap.The current validator effectively prevents
chunk_overlap >= chunk_size. As a complementary improvement to this configuration validation, consider ensuring thatchunk_sizeandchunk_overlapare strictly non-negative by using Pydantic'sFieldconstraints. This would prevent mathematically invalid values (like negative numbers) from passing model creation.For example, updating the field definitions (lines 20-21) to:
chunk_size: int = Field(default=4000, gt=0) chunk_overlap: int = Field(default=200, ge=0)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/crewai/src/crewai/knowledge/source/base_knowledge_source.py` around lines 32 - 46, Update the chunk_size and chunk_overlap field definitions in the knowledge source model to enforce chunk_size > 0 and chunk_overlap >= 0 using Pydantic Field constraints, while preserving their existing defaults. Keep _validate_chunk_overlap responsible for ensuring chunk_overlap remains smaller than chunk_size.lib/crewai/tests/knowledge/test_base_knowledge_source_chunk_overlap.py (1)
7-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse Pydantic's
ValidationErrorfor more precise exception testing.Although Pydantic's
ValidationErrorinherits from Python's built-inValueError(which allows this test to pass), it is more idiomatic and precise to explicitly test forValidationError. This ensures that you are strictly verifying Pydantic's validation behavior and not inadvertently passing the test if a standardValueErrorwere raised by an internal method.♻️ Proposed refactor
+from pydantic import ValidationError + def test_chunk_overlap_equal_to_chunk_size_is_rejected(): - with pytest.raises(ValueError, match="chunk_overlap"): + with pytest.raises(ValidationError, match="chunk_overlap"): StringKnowledgeSource(content="hello world", chunk_size=50, chunk_overlap=50) def test_chunk_overlap_greater_than_chunk_size_is_rejected(): - with pytest.raises(ValueError, match="chunk_overlap"): + with pytest.raises(ValidationError, match="chunk_overlap"): StringKnowledgeSource(content="hello world", chunk_size=50, chunk_overlap=60)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/crewai/tests/knowledge/test_base_knowledge_source_chunk_overlap.py` around lines 7 - 14, Update both chunk-overlap rejection tests, test_chunk_overlap_equal_to_chunk_size_is_rejected and test_chunk_overlap_greater_than_chunk_size_is_rejected, to assert Pydantic’s ValidationError instead of the broader ValueError, and import ValidationError from the appropriate Pydantic package.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@lib/crewai/src/crewai/knowledge/source/base_knowledge_source.py`:
- Around line 32-46: Update the chunk_size and chunk_overlap field definitions
in the knowledge source model to enforce chunk_size > 0 and chunk_overlap >= 0
using Pydantic Field constraints, while preserving their existing defaults. Keep
_validate_chunk_overlap responsible for ensuring chunk_overlap remains smaller
than chunk_size.
In `@lib/crewai/tests/knowledge/test_base_knowledge_source_chunk_overlap.py`:
- Around line 7-14: Update both chunk-overlap rejection tests,
test_chunk_overlap_equal_to_chunk_size_is_rejected and
test_chunk_overlap_greater_than_chunk_size_is_rejected, to assert Pydantic’s
ValidationError instead of the broader ValueError, and import ValidationError
from the appropriate Pydantic package.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 5346bfa5-6fd2-4d32-8fc9-88a2af8df143
📒 Files selected for processing (2)
lib/crewai/src/crewai/knowledge/source/base_knowledge_source.pylib/crewai/tests/knowledge/test_base_knowledge_source_chunk_overlap.py
Summary
BaseKnowledgeSource._chunk_text()— and 6 byte-for-byte identical copies ofit duplicated across
StringKnowledgeSource,JSONKnowledgeSource,PDFKnowledgeSource,TextFileKnowledgeSource,CSVKnowledgeSource, andExcelKnowledgeSource— compute the slicing step with no validation:chunk_overlap == chunk_size→ step is0→ValueError("range() arg 3 must not be zero"), a confusing error with no indication it's achunk_size/chunk_overlap misconfiguration.
chunk_overlap > chunk_size→ step is negative →range(0, len(text), negative)withstart(0) < stop(len(text))silently yields nothing →_chunk_textreturns[]→ the entire source content is dropped, noerror, no warning, nothing gets indexed.
Verified both independently with a real
StringKnowledgeSourceinstance(no mocking) before this fix — confirmed the exact
ValueErrormessage forthe equal case, and confirmed zero chunks / no exception at all for the
greater-than case.
Fix
Added a single
@model_validator(mode="after")onBaseKnowledgeSourcethat rejects
chunk_overlap >= chunk_sizeat construction time with a clearmessage. Every one of the 7 duplicated
_chunk_textimplementations readsself.chunk_size/self.chunk_overlapfrom the same inherited Pydanticfields, and Pydantic validators are inherited by subclasses — so this one
change on the base class protects all 7 call sites without touching each
file's duplicated method individually. Confirmed by direct instantiation:
StringKnowledgeSource(..., chunk_size=50, chunk_overlap=50)andchunk_overlap=60both now raiseValidationErrorimmediately, before anychunking is attempted.
Testing
Added
tests/knowledge/test_base_knowledge_source_chunk_overlap.py:chunk_overlap == chunk_size→ rejectedchunk_overlap > chunk_size→ rejectedchunk_overlap < chunk_size→ acceptedchunk_size=4000,chunk_overlap=200) → acceptedConfirmed red→green: reverting the source change reproduces "DID NOT RAISE
ValueError" for both bad-config tests; reapplying passes all 4.
Full
tests/knowledge/suite: 58 passed, no regressions.ruff check+ruff format --check+mypyall clean.Note on overlap
Open PR #5899 also touches
base_knowledge_source.py(adds adescription=to themetadatafield and threadsmetadatathrough_save_documents/_asave_documents) — different lines, no functionaloverlap with this change, but flagging it since both touch the same file.
AI-Generated disclosure
Implemented with Claude Code (Anthropic) — I independently reproduced both
failure modes with a real (non-mocked) knowledge source instance, verified
the fix protects all 7 duplicated call sites via Pydantic's validator
inheritance, and ran the full test suite before submitting.
Per CONTRIBUTING.md, AI-assisted PRs should carry the
llm-generatedlabel.As an external contributor I don't have permission to self-apply labels
(confirmed via
gh pr edit --add-label, GraphQL permission error) — happyfor a maintainer to apply it.