# Geocoding failures surface a validation error, not silent (0,0) coordinate storage

- **Pattern:** `ab-001044` (`directory-map-location.geocoding.geocoding-error-handling`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001044
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001044)

## Why it matters

Silent geocoding failure that stores (0,0) coordinates plants listings in the Gulf of Guinea — visibly off the map for most directories, or worse, clustered with other (0,0) entries in a way that makes them appear at a real but incorrect location. CWE-754 (Improper Check for Unusual Conditions) and CWE-20 (Improper Input Validation) both apply: the application accepts invalid geocoding output without surfacing an error. ISO 25010:2011 reliability is violated because the system produces incorrect outputs without notifying the user. From a business standpoint, silent (0,0) storage corrupts the directory's data integrity and is difficult to detect and backfill at scale.

## Severity rationale

High because silent (0,0) storage corrupts listing data permanently without user awareness, and the defect is difficult to detect and remediate after the fact at scale.

## Remediation

Reject listing creation when geocoding fails and surface a specific, actionable error message. Do not store a listing with null or (0,0) coordinates.

```ts
// src/app/api/listings/route.ts
export async function POST(req: Request) {
  const { address, name } = await req.json();

  const geocoded = await geocodeAddress(address);
  if (!geocoded || geocoded.confidence < 0.8) {
    return Response.json(
      { error: 'Address could not be verified. Please enter a more complete address, including city and postal code.' },
      { status: 400 }
    );
  }

  const listing = await db.listings.create({
    data: { name, address, latitude: geocoded.lat, longitude: geocoded.lng }
  });
  return Response.json(listing);
}
```

In the submission form, display the API error message directly rather than a generic fallback, so users understand what to correct. Handle all error paths: address not found, API timeout, rate limit exceeded — each should produce a distinct message.

## Detection

- **ID:** `geocoding-error-handling`
- **Severity:** `high`
- **What to look for:** Test the listing submission form with an invalid or ambiguous address. Check whether the form shows an error message to the user, or silently stores a default coordinate (0,0 or null). Look for error handling in the geocoding API endpoint.
- **Pass criteria:** When geocoding fails (address not found, API error, timeout), the submission form displays a clear error message within no more than 5 seconds. Enumerate all geocoding error paths (not found, API error, timeout, rate limit) and confirm each surfaces a user-facing message. Listings are not created with invalid coordinates. Users can correct the address and resubmit.
- **Fail criteria:** Geocoding failure is silent. Listings are stored with (0,0), null, or placeholder coordinates. No error shown to the user. Logging the error server-side without showing a message to the user does not count as pass.
- **Skip (N/A) when:** Geocoding is not used, or addresses are manually entered with pre-approved coordinates.
- **Detail on fail:** `"Submission form silently accepts invalid addresses and stores listings with coordinates (0, 0) instead of raising an error"` or `"Geocoding errors logged server-side but form shows no error message to user"`
- **Remediation:** Validate geocoding results and reject invalid submissions:

  ```ts
  // pages/api/listings.ts (Next.js)
  export default async function handler(req, res) {
    const { address, name } = req.body;

    // Geocode the address
    const geocoded = await geocodeAddress(address);
    if (!geocoded || geocoded.confidence < 0.8) {
      return res.status(400).json({
        error: 'Address could not be verified. Please enter a more complete address.'
      });
    }

    // Create listing with valid coordinates
    const listing = await db.listings.create({
      name,
      address,
      latitude: geocoded.lat,
      longitude: geocoded.lng
    });
    res.json(listing);
  }
  ```

  In the form:

  ```tsx
  const handleSubmit = async (formData) => {
    const res = await fetch('/api/listings', {
      method: 'POST',
      body: JSON.stringify(formData)
    });
    if (!res.ok) {
      const err = await res.json();
      setError(err.error);
      return;
    }
  };
  ```

## External references

- cwe CWE-754
- cwe CWE-20
- iso-25010 reliability

Taxons: error-resilience, data-integrity

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