NJ Municipality Lookup
CodebaseSrcDomain

Errors

Type-safe error classes for domain-specific failure modes. All errors are created using the `error-factory` pattern for consistency and type safety.

Domain Errors (domain/errors/)

Type-safe error classes for domain-specific failure modes. All errors are created using the error-factory pattern for consistency and type safety.

Error Classes

validation-error.ts

Input validation failures (bad user input, constraint violations).

throw new ValidationError("Municipality name cannot be empty");
throw new ValidationError("Invalid format", { field: "zipCode", value: "abc" });

address-not-found.ts

Address geocoding returned no results or low-confidence matches.

throw new AddressNotFoundError({ address: "999 Fake St, Newark, NJ" });

api-timeout.ts

External API request exceeded timeout threshold.

throw new ApiTimeoutError({ url: "https://geo.nj.gov/...", timeoutMs: 10000 });

invalid-api-response.ts

External API returned malformed or unexpected data structure.

throw new InvalidApiResponseError({ message: "Missing candidates array", url });

cache-error.ts

Cache operations failed (read/write/eviction errors).

throw new CacheError("Failed to evict entries", { attemptedCount: 10 });

invalid-address.ts

Address failed security validation (XSS patterns, SQL injection attempts).

throw new InvalidAddressError("Address contains dangerous patterns", {
  pattern: "<script>",
});

Error Factory Pattern

All errors use the generic createCustomError factory:

export const ValidationError = createCustomError<
  "ValidationError",
  Record<string, unknown>
>({
  name: "ValidationError",
});

Benefits:

  • Consistent structure across all errors
  • Type-safe data payloads
  • Automatic serialization (toJSON)
  • Stack traces preserved
  • Eliminates boilerplate

Usage Patterns

Throwing Errors

// Simple message
throw new ValidationError("Invalid input");

// With structured data
throw new ApiTimeoutError({
  url: "https://api.example.com",
  timeoutMs: 5000,
  attempt: 3,
});

Catching Errors

try {
  const result = await geocode(address);
} catch (error) {
  if (error instanceof AddressNotFoundError) {
    // Handle specific error type
    console.log(`Address not found: ${error.data.address}`);
  } else if (error instanceof ApiTimeoutError) {
    console.log(`Timeout after ${error.data.timeoutMs}ms`);
  }
  throw error;
}

Serialization

All errors serialize cleanly for logging and API responses:

const error = new ValidationError("Bad input", { field: "email" });
console.log(JSON.stringify(error)); // { name, message, data, stack }

Testing

Each error has unit tests verifying:

  • Correct error name and instanceof checks
  • Message formatting with data
  • Data payload structure
  • JSON serialization
  • Stack trace preservation

On this page