How Context Limits Show Up on a Real Repository
The repository had 412 files. That number matters, because the assistant had been told to read the whole thing before answering a question about where authentication was configured. It read 38 files, produced a confident summary, and missed the one place the token lifetime was actually set. The developer who trusted it spent forty minutes chasing a session bug that did not exist.
This is what context limits look like when they stop being an abstraction. Every model has a window, a hard ceiling on how many tokens it can hold at once, and on a real codebase that ceiling turns into a set of specific, repeatable failure modes. The interesting part is that the failures cluster. They show up in the same places, wearing the same disguises, and once a person has watched for them a few times they become predictable enough to design around.
A context window is measured in tokens, roughly three quarters of a word each in English, and modern models advertise figures in the hundreds of thousands. Those numbers sound enormous until a repository gets involved. A single large source file can run several thousand tokens. A lockfile can swallow tens of thousands. The model does not see a project the way an editor sees a project, with a tree and a sense of scale. It sees a flat sequence, and when the sequence overflows, something has to give.
The summary that quietly deletes the middle
Most tools handle overflow by summarizing. Older turns get compressed, retrieved chunks get truncated, and the model proceeds on a condensed memory of what came before. This works well enough for chat. On a repository it produces a signature error: the beginning and the end of a file survive, and the middle evaporates.
Watch a model reason about a 900-line module and the pattern appears. It will quote the imports at the top accurately. It will describe the exported function at the bottom accurately. Ask about the validation logic in the middle and the answer gets vague, or worse, gets invented. The truncation is invisible in the output. Nothing in the response says "I only saw the first 200 and last 200 lines." The model fills the gap with plausible code, and plausible code is the most expensive kind of wrong.
A senior engineer reading the same file would never make that mistake, because a person skims and knows what they skipped. The model has no equivalent awareness. Its memory of the file is the file it was given, and it cannot tell the difference between a section it never received and a section that was never there.
When the config lives three directories away
Repositories are built on indirection. A function reads an environment variable. The variable is set in a deployment manifest. The manifest references a secret managed somewhere else. The actual value traces back to a config file two directories up and named something unhelpful like settings.prod.json.
Following that chain requires holding several files in view at once and noticing the links between them. Context limits punish exactly this. Each hop costs tokens, and by the third or fourth hop the earliest files have been pushed out or compressed into a sentence. The model ends up reasoning about a chain whose first link it can no longer see.
The result is an answer that is locally correct and globally wrong. It will explain the function accurately and the environment variable accurately and still miss that the deployment manifest overrides both. A developer who knows the codebase spots the gap in seconds. A developer new to the project, which is precisely the person most likely to ask, does not.
Retrieval hands over the wrong ten files
Retrieval augmented generation is the usual fix for context limits: instead of stuffing everything in, search the repository for relevant chunks and feed only those. The approach is sound in principle and fragile in practice, and the fragility shows up on real code in a specific way.
Semantic search matches on similarity of wording. Code that solves a problem often does not share vocabulary with the problem description. A bug report says "users get logged out too fast." The code that controls session duration is called something like refreshWindowMs and lives in a file with no mention of users or logging out. The retrieval step surfaces the login page, the logout handler, and three files that mention "session" in a comment, while the actual cause sits outside the top ten results.
There is a second-order effect here that gets less attention. Retrieval returns chunks, not files, and chunks cut across boundaries. A function gets split from the class that gives it meaning. A constant gets separated from the place it is used. The model receives fragments that look self-contained and reasons about them as if they were whole, and the seams where the cuts happened are exactly where the bugs live.
The stale view of a moving repository
A context window is a snapshot. The repository is a living thing, and on an active team it changes while the model is thinking. A branch gets rebased. A function gets renamed. A file the model read ten minutes ago no longer exists in the form it saw.
This produces a failure mode that is easy to miss because it looks like confidence. The model recommends calling a function that was renamed two commits ago. It references a config key that was removed. It explains an architecture that the team migrated away from last quarter. The recommendations are internally consistent and externally outdated, and the person reading them has to reconcile two versions of reality in their head.
Long-running agent sessions make this worse. An agent that has been working for an hour holds an hour-old picture of the codebase, and if it has been editing files along the way, its picture of what it changed is itself compressed. It can lose track of its own modifications, which is a strange sentence to write about a tool, and yet it happens routinely on large refactors.
Naming collisions that a human filters automatically
Real repositories contain duplicates. There are three functions called validate in different modules, two utilities named formatDate with different behavior, and a helper called parseConfig that appears in four places and does four different things. A human navigates this with a mental map of where things live and a habit of checking imports. The map is built from experience and it does not cost tokens.
A model working from retrieved chunks has no map. It sees a chunk that calls validate, retrieves a definition of validate from a different module, and reasons as if they were the same function. The output reads perfectly. The logic is sound. The code references the wrong validate, and the error surfaces at runtime, far from the point of confusion.
This is the pattern that separates context limits from ordinary model errors. The model is not confused about syntax or logic. It is working correctly on the wrong slice of reality, and the slice is wrong because the window could not hold enough of the repository to show that two things with the same name are different.
What the failures have in common
Every one of these cases shares a structure. The model produces a response that is coherent, specific, and confidently stated, and the error is invisible from inside the response. There is no hedge, no note about truncated input, no flag on the retrieved chunk that says "this might be the wrong validate."
That invisibility is the real cost. A model that said "I could not see the middle of this file" would be easy to work with. A model that silently substitutes plausible code for the section it never received forces the developer to verify everything, which erodes the value of asking in the first place.
The failures also share a location. They cluster around the boundaries of the window and the seams of retrieval: the middle of long files, the ends of dependency chains, the edges of chunks, the gap between the snapshot and the present. A developer who wants to catch them learns to look at exactly those places, and the looking is cheap once the habit forms.
A working habit for reading model answers on code
None of this argues against using these tools on real repositories. It argues for reading their output the way a careful editor reads a draft: looking for the specific places where the seams show.
When a model describes a long file, ask it to quote the relevant lines. A quote that skips the middle is a tell. When it traces a config value, ask it to name every file in the chain and check that the chain is complete. When it references a function, confirm the import path matches the module it claims. When a session has run long, ask it to restate its current understanding of the changed files before trusting the next recommendation.
These checks take seconds and they catch the failures above, because the failures live at the boundaries and the checks target the boundaries directly. The model is a fast reader with a small, lossy memory. Treating it that way, and verifying the places where a lossy memory fails, keeps the speed without inheriting the quiet errors.
The developer from the opening, the one who lost forty minutes to a session bug that did not exist, now runs a single habit before trusting any summary of an unfamiliar repository: ask the model which files it actually read. The answer is usually shorter than expected, and the gap between that answer and the full file count is where the next forty minutes would have gone.

