# eslint jsx-a11y alt-text rule failed missing alt - how to fix it

## TL;DR

Add alt props to every img, area, input type image, and object in JSX: meaningful images get descriptive text, decorative ones get empty alt. The rule fails on missing or undefined alt, not on empty. One line of why: catching it in lint means the violation never ships to axe or a screen reader user.

## The error, verbatim

```text
/app/src/components/Hero.jsx
  8:7  error  img elements must have an alt prop, either with meaningful text, or an empty string for decorative images  jsx-a11y/alt-text

```

## Fix it step by step

### Step 1: Reproduce on one file

```bash
npx eslint src/components/Hero.jsx --rule '{"jsx-a11y/alt-text": "error"}'
```

Expected: ESLint prints the alt-text error with line and column.

### Step 2: Find every offending element

```bash
npx eslint src | rg 'jsx-a11y/alt-text' | head -20
```

Expected: Full list across the codebase, including area and input type image elements.

### Step 3: Add alt props

```bash
rg -n --glob '*.{jsx,tsx}' 'img src' src | rg -v 'alt=' | head -20
```

Expected: Shows img elements missing alt entirely. (Adjust the pattern if your search tool differs.)

### Step 4: Re-lint

```bash
npx eslint src | rg -c 'jsx-a11y/alt-text' || echo 0
```

Expected: Prints 0. A follow-up axe run on image-alt should also pass now.

### Step 5: Enforce it in CI

```bash
npx eslint src --max-warnings 0 | tail -3
```

Expected: Clean output; add the lint command to CI with max-warnings 0 so the violation cannot come back.

## When to use this skill

- Your linter output names this exact jsx-a11y / a11y rule
- You want the violation fixed at author time so it never reaches axe or CI
- You are adding the rule to a shared eslint config and need the fix pattern

## When NOT to use this skill

- The failure comes from axe-core or lighthouse at runtime, not from lint
- You plan to disable the rule project-wide, this skill shows the fix, not the escape hatch

## Compatibility

eslint-plugin-jsx-a11y 6.7+ with eslint 8 or 9. The rule covers img, area, input[type=image], and object elements. Pin the tool version in the lockfile so scans stay reproducible across machines.

## Variant phrasings

### img elements must have an alt prop

The default message, same fix.

### jsx-a11y alt-text object element

The rule also checks object elements, which need a title or aria-label plus inner text.

### the rule fires in the editor too

With the eslint extension installed, the same error appears inline while typing; the fix is identical.

## Why it happens

JSX img elements without an alt prop are the most common way missing-alt ships, because TypeScript does not require the prop and nothing else checks. The rule treats a missing or undefined alt as an error but accepts an empty string, matching the axe image-alt semantics. Dynamic alt values (alt={caption}) pass as long as the prop exists, so the rule cannot catch empty-at-runtime values. Linter rules catch the violation at author time, which is cheaper than any runtime fix. When this rule fires across many files, fix the shared component and mention it in team onboarding so new code does not reintroduce it.

## Edge cases

- alt={undefined} still fails, the prop must be present with a string value.
- For object elements, provide title or aria-label plus fallback text content inside.
- Decorative images: alt="" is correct, do not write alt text like decorative image.
- After fixing, run the whole lint suite once; a11y rules interact and one fix can surface the next violation.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_9_XQH8E97nLmk4rxfEW4Qg
