or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

examples

edge-cases.mdreal-world-scenarios.md
index.md
tile.json

edge-cases.mddocs/examples/

Edge Cases and Error Handling

Advanced scenarios, edge cases, and comprehensive error handling patterns.

Common Error Scenarios

Missing Configuration

Error: ConfigMissingError - components.json not found

import { getRegistryItems, ConfigMissingError } from 'shadcn/registry';

try {
  const items = await getRegistryItems(['@shadcn/button']);
} catch (error) {
  if (error instanceof ConfigMissingError) {
    // Solution: Initialize project
    console.error('Project not initialized. Run: npx shadcn init');
  }
}

CLI Exit Code: 2

# Error: components.json not found
# Solution: Run npx shadcn init first
npx shadcn init

Component Not Found

Error: RegistryNotFoundError - Item not found in registry

import { getRegistryItems, RegistryNotFoundError } from 'shadcn/registry';
import { searchRegistries } from 'shadcn/registry';

try {
  const items = await getRegistryItems(['@shadcn/nonexistent']);
} catch (error) {
  if (error instanceof RegistryNotFoundError) {
    // Try to find similar items
    const searchResults = await searchRegistries(['@shadcn'], {
      query: 'nonexistent',
      limit: 5
    });
    
    if (searchResults.items.length > 0) {
      console.log('Did you mean:', searchResults.items.map(i => i.name).join(', '));
    }
  }
}

CLI Exit Code: 3

# Error: Component not found in registry
# Solution: Search for correct component name
npx shadcn search @shadcn --query button

Registry Not Configured

Error: RegistryNotConfiguredError - Registry not in components.json

import { getRegistryItems, RegistryNotConfiguredError } from 'shadcn/registry';

try {
  const items = await getRegistryItems(['@custom/button']);
} catch (error) {
  if (error instanceof RegistryNotConfiguredError) {
    // Solution: Add registry to components.json
    console.error(`Registry not configured: ${error.context?.registry}`);
    if (error.suggestion) {
      console.log('Suggestion:', error.suggestion);
    }
  }
}

CLI Exit Code: 3

Network Errors

Error: RegistryFetchError - Network or fetch errors

import { getRegistryItems, RegistryFetchError } from 'shadcn/registry';

async function fetchWithRetry(items: string[], maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await getRegistryItems(items);
    } catch (error) {
      if (error instanceof RegistryFetchError && attempt < maxRetries) {
        // Wait before retry (exponential backoff)
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
        continue;
      }
      throw error;
    }
  }
}

CLI Exit Code: 3

Authentication Errors

Error: RegistryUnauthorizedError - Authentication required

import { getRegistryItems, RegistryUnauthorizedError } from 'shadcn/registry';

try {
  const items = await getRegistryItems(['@private/button']);
} catch (error) {
  if (error instanceof RegistryUnauthorizedError) {
    // Check for missing environment variables
    console.error('Authentication required. Check registry configuration and ensure required environment variables are set.');
    console.error('Missing variables:', error.context);
  }
}

CLI Exit Code: 3

Edge Cases

Partial Failures in Batch Operations

When adding multiple components, some may fail:

import { getRegistryItems, RegistryNotFoundError } from 'shadcn/registry';

async function batchGetItems(itemNames: string[]) {
  const results: Array<{ name: string; item?: any; error?: string }> = [];
  
  // Process items individually to handle partial failures
  for (const itemName of itemNames) {
    try {
      const [item] = await getRegistryItems([itemName]);
      results.push({ name: itemName, item });
    } catch (error) {
      if (error instanceof RegistryNotFoundError) {
        results.push({ name: itemName, error: `Not found: ${error.message}` });
      } else {
        results.push({ name: itemName, error: `Error: ${error.message}` });
      }
    }
  }
  
  return results;
}

CLI Behavior: When adding multiple components, if one fails, the command may partially succeed. Check output for individual component status.

Circular Dependencies

Error: Circular dependency detected

import { resolveRegistryItems } from 'shadcn';
import { RegistryError } from 'shadcn/registry';

async function safeResolveItems(items: string[]) {
  try {
    return await resolveRegistryItems(items);
  } catch (error) {
    if (error instanceof RegistryError && error.code === 'VALIDATION_ERROR') {
      if (error.message.includes('circular') || error.message.includes('dependency')) {
        throw new Error(
          `Circular dependency detected in registry items: ${items.join(', ')}. ` +
          `This usually indicates a registry configuration issue.`
        );
      }
    }
    throw error;
  }
}

CLI Exit Code: 4

Component Already Exists

When adding a component that already exists:

# Without --overwrite flag, command will prompt
npx shadcn add button

# With --overwrite flag, overwrites without prompting
npx shadcn add button --yes --overwrite

CLI Exit Code: 0 (with prompt) or 0 (with --overwrite)

Invalid Component Name Format

Error: Validation error - Invalid component name

// Invalid: Missing registry prefix
await getRegistryItems(['button']); // May work if default registry configured

// Valid: With registry prefix
await getRegistryItems(['@shadcn/button']);

// Invalid: Malformed name
await getRegistryItems(['@shadcn/']); // Validation error

CLI Exit Code: 4

Configuration in Parent Directory

Configuration discovery searches parent directories:

import { getRegistriesConfig } from 'shadcn';
import { findUp } from 'find-up';
import { dirname } from 'path';

// Works even if components.json is in parent directory
const configPath = await findUp('components.json', { cwd: process.cwd() });
const configDir = dirname(configPath);
const { registries } = await getRegistriesConfig(configDir);

Workspace/Monorepo Configurations

Handle multiple components.json files:

import { getRegistriesConfig } from 'shadcn';
import { findUp } from 'find-up';
import { dirname } from 'path';

async function getWorkspaceConfigs(rootDir: string) {
  const configs: Array<{ path: string; config: any }> = [];
  let currentDir = rootDir;
  
  while (currentDir) {
    const configPath = await findUp('components.json', { cwd: currentDir });
    if (configPath) {
      const configDir = dirname(configPath);
      const { registries } = await getRegistriesConfig(configDir);
      configs.push({ path: configPath, config: { registries } });
      
      const parentDir = dirname(configDir);
      if (parentDir === currentDir) break;
      currentDir = parentDir;
    } else {
      break;
    }
  }
  
  return configs;
}

Package Manager Not Available

CLI Exit Code: 1

# Error: Package manager (npm/yarn/pnpm) not found
# Solution: Ensure package manager is installed and in PATH
which npm
# or
which yarn
# or
which pnpm

File System Permissions

CLI Exit Code: 1

# Error: Permission denied when writing files
# Solution: Check file system permissions
chmod -R u+w components/

Network Timeouts

Handle network timeouts gracefully:

import { getRegistryItems, RegistryFetchError } from 'shadcn/registry';

async function fetchWithTimeout(items: string[], timeoutMs = 5000) {
  const timeoutPromise = new Promise((_, reject) => {
    setTimeout(() => reject(new Error('Request timeout')), timeoutMs);
  });
  
  try {
    return await Promise.race([
      getRegistryItems(items),
      timeoutPromise
    ]);
  } catch (error) {
    if (error instanceof RegistryFetchError) {
      throw new Error(`Network error: ${error.message}`);
    }
    throw error;
  }
}

Error Recovery Strategies

Comprehensive Error Handler

import {
  getRegistryItems,
  RegistryError,
  RegistryNotFoundError,
  RegistryNotConfiguredError,
  ConfigMissingError,
  RegistryFetchError,
  RegistryUnauthorizedError
} from 'shadcn/registry';
import { searchRegistries } from 'shadcn/registry';

async function safeGetRegistryItems(items: string[]) {
  try {
    return await getRegistryItems(items);
  } catch (error) {
    if (error instanceof ConfigMissingError) {
      throw new Error('Project not initialized. Run: npx shadcn init');
    } else if (error instanceof RegistryNotConfiguredError) {
      throw new Error(`Registry not configured. Add to components.json: ${error.suggestion}`);
    } else if (error instanceof RegistryNotFoundError) {
      // Try to find similar items
      const searchTerm = items[0].split('/').pop() || items[0];
      const searchResults = await searchRegistries(['@shadcn'], {
        query: searchTerm,
        limit: 5
      });
      
      if (searchResults.items.length > 0) {
        throw new Error(
          `Item not found: ${items[0]}. Did you mean: ${searchResults.items.map(i => i.addCommandArgument).join(', ')}?`
        );
      }
      
      throw new Error(`Item not found: ${items[0]}. Try: npx shadcn search ${searchTerm}`);
    } else if (error instanceof RegistryUnauthorizedError) {
      throw new Error(
        `Authentication required. Check registry configuration and ensure required environment variables are set.`
      );
    } else if (error instanceof RegistryFetchError) {
      throw new Error(`Network error: ${error.message}. Please check your connection and try again.`);
    } else if (error instanceof RegistryError) {
      throw new Error(`Registry error: ${error.code} - ${error.message}`);
    }
    throw error;
  }
}

CLI Exit Code Reference

Exit CodeMeaningCommon Causes
0SuccessOperation completed successfully
1General errorFile system, network, package manager errors
2Configuration errorMissing or invalid components.json
3Registry errorItem not found, network error, authentication failure
4Validation errorInvalid input, circular dependency

Best Practices

  1. Always check exit codes when using CLI programmatically
  2. Handle partial failures in batch operations
  3. Implement retry logic for network errors
  4. Validate input before making API calls
  5. Provide user-friendly error messages based on error codes
  6. Check configuration before registry operations
  7. Use search to find similar items when not found

See CLI Commands Reference for complete exit code documentation.