Skip to content

Error Handling

Learn how to handle errors gracefully with rut.ts.

Safe Mode#

Throwing helpers support throwOnError: false to return null instead of throwing errors.

Without Safe Mode (Default)#

TypeScript
import { clean, format, decompose } from 'rut.ts'
 
try {
  clean('invalid')
} catch (error) {
  console.error(error) // Error: Invalid RUT input
}
 
try {
  format('abc')
} catch (error) {
  console.error(error) // Error: Invalid RUT input
}
 
try {
  decompose('123')
} catch (error) {
  console.error(error) // Error: Invalid RUT input
}

Error messages are intentionally generic so invalid RUT values are not echoed into logs or traces.

With Safe Mode#

TypeScript
import { clean, format, decompose } from 'rut.ts'
 
const cleaned = clean('invalid', { throwOnError: false })
console.log(cleaned) // null
 
const formatted = format('abc', { throwOnError: false })
console.log(formatted) // null
 
const parts = decompose('123', { throwOnError: false })
console.log(parts) // null

Graceful Error Handling#

Form Validation#

TypeScript
import { validate, format, clean } from 'rut.ts'
 
function validateRutInput(input: string) {
  // Quick format check
  const formatted = format(input, {
    incremental: true,
    throwOnError: false,
  })
 
  if (!formatted) {
    return { valid: false, error: 'Invalid format' }
  }
 
  // Full validation
  if (!validate(formatted)) {
    return { valid: false, error: 'Invalid RUT or verifier' }
  }
 
  // Strict validation
  if (!validate(formatted, { strict: true })) {
    return {
      valid: false,
      error: 'Suspicious RUT pattern detected',
    }
  }
 
  // Clean for storage
  const cleaned = clean(formatted)
 
  return {
    valid: true,
    cleaned,
    formatted,
  }
}

API Route Handler#

TypeScript
import { validate, clean } from 'rut.ts'
 
export async function POST(request: Request) {
  const body = await request.json()
 
  // Validate RUT with safe mode
  if (!validate(body.rut)) {
    return Response.json({ error: 'Invalid RUT' }, { status: 400 })
  }
 
  // Clean RUT safely
  const cleaned = clean(body.rut, { throwOnError: false })
  if (!cleaned) {
    return Response.json({ error: 'Cannot process RUT' }, { status: 400 })
  }
 
  // Process...
  return Response.json({ success: true, rut: cleaned })
}

Chain Operations Safely#

TypeScript
import { clean, decompose, calculateVerifier } from 'rut.ts'
 
function processRutSafely(input: string) {
  // Step 1: Clean
  const cleaned = clean(input, { throwOnError: false })
  if (!cleaned) {
    return { error: 'Invalid RUT format', step: 'clean' }
  }
 
  // Step 2: Decompose
  const parts = decompose(cleaned, { throwOnError: false })
  if (!parts) {
    return { error: 'Cannot decompose RUT', step: 'decompose' }
  }
 
  // Step 3: Verify
  const calculated = calculateVerifier(parts.body, { throwOnError: false })
  if (!calculated) {
    return { error: 'Invalid body', step: 'calculate' }
  }
 
  if (calculated !== parts.verifier) {
    return { error: 'Verifier mismatch', step: 'verify' }
  }
 
  return {
    success: true,
    body: parts.body,
    verifier: parts.verifier,
  }
}

Error Messages#

Custom Error Messages#

TypeScript
import { validate, clean } from 'rut.ts'
 
function getRutError(rut: string): string | null {
  if (!rut) return 'RUT is required'
 
  const cleaned = clean(rut, { throwOnError: false })
  if (!cleaned) {
    if (rut.length < 8) return 'RUT too short'
    if (rut.length > 12) return 'RUT too long'
    return 'Invalid RUT format'
  }
 
  if (!validate(cleaned)) {
    return 'Invalid verifier digit'
  }
 
  if (!validate(cleaned, { strict: true })) {
    return 'Suspicious RUT pattern (e.g., 11.111.111-1)'
  }
 
  return null
}
 
// Usage
const error = getRutError(userInput)
if (error) {
  showErrorToUser(error)
}

Localized Errors#

TypeScript
import { validate } from 'rut.ts'
 
const errorMessages = {
  en: {
    required: 'RUT is required',
    invalid: 'Invalid RUT',
    suspicious: 'Suspicious pattern detected',
  },
  es: {
    required: 'El RUT es requerido',
    invalid: 'RUT inválido',
    suspicious: 'Patrón sospechoso detectado',
  },
}
 
function validateWithLocale(rut: string, locale: 'en' | 'es' = 'es') {
  const messages = errorMessages[locale]
 
  if (!rut) return messages.required
  if (!validate(rut)) return messages.invalid
  if (!validate(rut, { strict: true })) return messages.suspicious
 
  return null
}

TypeScript Type Guards#

TypeScript
import { validate, clean } from 'rut.ts'
 
type Result<T> = { success: true; data: T } | { success: false; error: string }
 
function parseRut(input: string): Result<string> {
  const cleaned = clean(input, { throwOnError: false })
 
  if (!cleaned) {
    return { success: false, error: 'Invalid format' }
  }
 
  if (!validate(cleaned)) {
    return { success: false, error: 'Invalid verifier' }
  }
 
  return { success: true, data: cleaned }
}
 
// Usage with type narrowing
const result = parseRut(userInput)
if (result.success) {
  // TypeScript knows result.data is string
  console.log(result.data)
} else {
  // TypeScript knows result.error is string
  console.error(result.error)
}

Best Practices#

Always use safe mode (throwOnError: false) when handling user input to avoid unexpected crashes.

In incremental mode, validation will fail for incomplete RUTs. Only validate on blur or submit.

Use strict mode ({ strict: true }) in production to reject placeholder RUTs like 11.111.111-1.