---
title: "Context-Blind Naming"
type: "ai-smell"
slug: "context-blind-naming"
url: "http://localhost:3000/en/ai-smells/context-blind-naming.md"
category: "Clarity"
description: "An AI assistant names new code with generic placeholders or a fresh convention that ignores the repository's existing identifiers and domain vocabulary, eroding readability and spawning duplicate, mis-described concepts."
---
# Context-Blind Naming

> An AI assistant names new code with generic placeholders or a fresh convention that ignores the repository's existing identifiers and domain vocabulary, eroding readability and spawning duplicate, mis-described concepts.

## Signs and Symptoms

A reviewer spots Context-Blind Naming when the names in an AI-authored diff are locally plausible but disconnected from the surrounding repo. Tell-tales:

* **Generic placeholders in domain code:** `data`, `result`, `temp`, `item`, `obj`, `payload`, `response`, `value`, `handleStuff`, `processData` where the module already speaks a specific language (`grossPremium`, `Customer`, `getCustomerById`).
* **Convention drift:** a `snake_case` symbol dropped into a `camelCase` file, a missing `is`/`has` boolean prefix, or a new CRUD verb (`fetch*`) in a codebase that standardized on `get*`. Each diff "follows whichever style it last encountered, introducing a fourth convention. Then a fifth."
* **Synonym sprawl / duplicate concepts:** the AI invents `fetchUser` when `getCustomerById` already exists, or mixes `customer`/`client`/`user` for one entity — re-implementing instead of reusing.
* **Names that describe mechanism, not intent — or lie about behavior:** `processData()` that actually computes sales tax. Agents (and the next agent) "read `processData()` and proceed as if that name tells the full story," so the wrong meaning propagates to every call site.

```ts
// Repo already exports getCustomerById(id: CustomerId): Promise<Customer>
// AI adds a near-duplicate with context-blind names:
async function fetchData(id: string) {          // generic verb, loose type
  const result = await db.query("select * from customers where id = $1", [id]);
  const temp = result.rows[0];                  // 'temp' hides that it's a Customer
  return temp;                                  // nothing here says "Customer"
}

```

## Reasons for the Problem

**Why models produce it**

* **Next-token frequency bias.** Across the training corpus, `data`/`result`/`temp`/`foo` are the highest-probability identifiers, especially in the tutorial and boilerplate code LLMs ingest heavily. Generating the _statistically average_ name is exactly what a next-token predictor is optimized to do, which smooths domain intent away ([Towards Data Science](https://towardsdatascience.com/the-missing-curriculum-essential-concepts-for-data-scientists-in-the-age-of-ai-coding-agents/)).
* **No (or truncated) repo context.** The model rarely sees the sibling module's glossary or the existing `getCustomerById`. GitClear ties the duplication surge directly to this: the assistant "is less likely to propose reusing a similar function elsewhere... partly because of limited context size" ([GitClear 2025](https://www.gitclear.com/ai%5Fassistant%5Fcode%5Fquality%5F2025%5Fresearch)).
* **Local optimization / weak refactoring instinct.** Each turn optimizes the immediate prompt, "without considering cumulative architectural impact." OX Security found _Avoidance of Refactors_ in 80–90% of AI code, so the model adds a freshly named symbol rather than rename or reuse an existing one ([OX report](https://www.prnewswire.com/news-releases/ox-report-ai-generated-code-violates-engineering-best-practices-undermining-software-security-at-scale-302592642.html)).
* **Training-cutoff staleness.** Conventions and API names from older corpora resurface even after a project has moved on.

**Why it hurts**

* **Readability/maintainability:** names are a codebase's primary documentation; generic ones force every reader to re-derive intent from the body.
* **Duplication and defects:** renaming a concept spawns a parallel implementation. GitClear measured an \~8x rise in duplicated blocks and copy/paste overtaking moved (refactored) lines for the first time in 2024; clones carry an estimated 15–50% more defects.
* **Agent feedback loop (the AI-specific harm):** names are the interface the _next_ agent reads at face value. A misleading or generic name "propagates errors through all agent-generated code that builds upon it" ([AI Pattern Book](https://aipatternbook.com/naming)).
* **Review load & correctness:** reviewers must mentally map `temp`/`data` back to domain concepts, which hides bugs; misleading names cause wrong usage at call sites.
* **Security/audit blind spots:** a secret or token parked in a var named `data`/`tmp` slips past name-based greps and review attention.

Note: research like arXiv [2509.20491](https://arxiv.org/abs/2509.20491) shows static tools catch _local, explicit_ smells well, but the domain-meaning facet here is value/intent-dependent and largely escapes automated detection.

## Treatment

**Review & prompting tactics**

* **Feed the conventions and glossary into context.** Keep a short naming guide (casing, boolean prefixes, CRUD verbs, domain terms) in `CLAUDE.md`/style docs and require the model to follow it. Apply domain-glossary terms consistently so synonyms collapse to one word.
* **Force reuse before creation.** Prompt: "Search the repo for an existing function/type for this before adding one; reuse it." This directly counters the duplicate-concept failure GitClear and OX flag.
* **Name things in the prompt.** "Name the handler `createRefund`" beats "add refund processing." Specify domain names (`monthlyRevenue`, not `float1`).
* **Require the linter + duplication scan to run** on the diff (naming-convention + `id-denylist` \+ jscpd) and have the model fix violations rather than you doing it by hand.

**The refactor** — apply _Rename Variable/Function_ (Fowler's "Change Function Declaration"), fixing the **Mysterious Name** smell, and _Consolidate Duplicate Code_ by reusing the existing symbol instead of the new one.

Before:

```ts
async function fetchData(id: string) {
  const result = await db.query("select * from customers where id = $1", [id]);
  const temp = result.rows[0];
  return temp;
}

```

After (reuse the existing repository fn; intention-revealing, convention-matching names and types):

```ts
// Don't re-query — reuse getCustomerById and keep the domain vocabulary.
async function getCustomerById(id: CustomerId): Promise<Customer | null> {
  const { rows } = await db.query<Customer>(
    "select * from customers where id = $1",
    [id],
  );
  return rows[0] ?? null;
}

```

If a misleading name already shipped, rename it to match behavior (`processData` → `calculateSalesTax`) before building on it, so downstream agents and humans inherit the correct signal.

## Detected by

- **ESLint (core)** `id-denylist` — Disallow specified identifiers (https://eslint.org/docs/latest/rules/id-denylist)
- **ESLint (core)** `id-length` — Enforce minimum/maximum identifier length (https://eslint.org/docs/latest/rules/id-length)
- **typescript-eslint** `@typescript-eslint/naming-convention` — Enforce naming conventions (casing/prefixes) (https://typescript-eslint.io/rules/naming-convention/)
- **eslint-plugin-unicorn** `unicorn/prevent-abbreviations` — Prevent abbreviations / overly generic names (https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prevent-abbreviations.md)
- **SonarQube / SonarSource** `typescript:S117` — Local variable and parameter names should comply with a naming convention (https://rules.sonarsource.com/typescript/RSPEC-117/)
- **jscpd** `copy-paste-detection` — Detects duplicate blocks created when a renamed concept duplicates an existing one (https://github.com/kucherenko/jscpd)
