# Config object key references resolve

- **Pattern:** `ab-000038` (`ai-slop-hallucinations.data-references.config-object-keys-resolve`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000038
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000038)

## Why it matters

A reference like `config.stripe.priceIds.pro` that does not exist in the config object evaluates to `undefined` at runtime, which then propagates into a Stripe API call as `{ price: undefined }` and produces a confusing `No such price` error in logs — not a crash at the config call site. Reference integrity at the configuration layer matters because the failure surfaces far downstream, often in a webhook handler where the original intent is lost. AI tools invent config keys confidently.

## Severity rationale

Low because the failure only surfaces in code paths that exercise the bad key, though the downstream error can be misleading.

## Remediation

Define the config object as the single source of truth in `src/lib/config.ts` and use `as const` so TypeScript catches typos at build time under `tsc --noEmit`:

```ts
export const config = {
  stripe: {
    priceIds: { pro: 'price_xxx', team: 'price_yyy' },
  },
} as const
```

Either add the missing key to the object or fix the reference to match the real path.

## Detection

- **ID:** `config-object-keys-resolve`
- **Severity:** `low`
- **What to look for:** Look for a project-level config object file matching `config.{ts,js,mjs}`, `lib/config.{ts,js,mjs}`, `src/config.{ts,js,mjs}`, `src/lib/config.{ts,js,mjs}`, `app/config.{ts,js,mjs}`. If such a file exists AND exports a literal object (not a function), build a map of `CONFIG_KEYS` from the object's structure. Then walk source files for references like `config.X.Y`, `CONFIG.X.Y`, `appConfig.X.Y` (matching the config import name) and check whether the key paths exist in the config object. Count all config key references, total resolved, total unresolved.
- **Pass criteria:** 100% of config key references map to keys defined in the config object. Report: "X config key references inspected, Y resolved, 0 unresolved."
- **Fail criteria:** At least 1 config reference accesses a key that does not exist in the config object.
- **Skip (N/A) when:** No project-level config object file exists OR the config file exports a function/class instead of a literal object (dynamic config).
- **Detail on fail:** `"2 unresolved config keys: config.stripe.priceIds.pro (config has stripe.products.pro), config.email.fromAddress (config has email.from)"`
- **Remediation:** Config key hallucinations result in `undefined` at runtime, often with confusing error messages. Fix each reference to match the actual config schema, or update the config file to include the missing key:

  ```ts
  // src/lib/config.ts — single source of truth
  export const config = {
    stripe: {
      priceIds: {
        pro: 'price_xxx',
        team: 'price_yyy',
      },
    },
    email: {
      fromAddress: 'noreply@example.com',
    },
  } as const

  // src/app/checkout/page.tsx
  import { config } from '@/lib/config'
  // Now config.stripe.priceIds.pro resolves correctly
  ```

  Better: use TypeScript's `as const` and let the compiler catch typos at build time via `tsc --noEmit`.

Taxons: reference-integrity

HTML version: https://auditbuffet.com/patterns/ab-000038
