๐Ÿ“ commands/add-dir/ ยท 05_error_feedback_system.md

Chapter 5: Error Feedback System

๐Ÿ“„ commands/add-dir/05_error_feedback_system.md

Chapter 5: Error Feedback System

Welcome to the final chapter! In Chapter 4: State & Permission Management, we successfully updated the application's memory to grant access to directories.

But we left one big question unanswered: What happens when things go wrong?

Motivation: The "Grumpy Robot"

By default, computers are terrible at communicating problems. If a user tries to access a folder they aren't allowed to see, the computer usually spits out something like this:

Error: EACCES: permission denied, stat '/etc/shadow'
    at Object.statSync (fs.js:1086:3)
    at ...

This is the "Grumpy Robot" response. It scares beginners and frustrates experts.

The Error Feedback System is designed to act as a translator. It catches these scary technical codes and turns them into helpful advice.

The Use Case

Imagine the user makes a typo or tries to add a file instead of a folder:

my-cli add-dir ./my-photo.png

Our Goal: Instead of crashing with a stack trace, we want to display:

./my-photo.png is not a directory. Did you mean to add the parent directory?

In this chapter, we will build the logic to catch these errors and format them beautifully.

Concept: Error Grouping

Operating systems have hundreds of different error codes (ENOENT, ENOTDIR, EPERM, etc.).

We don't want to write a unique error message for every single one. Instead, we group them into Logical Categories.

  1. "I can't see it": The file is missing (ENOENT) OR I'm not allowed to look at it (EACCES).
  2. "Wrong Type": I see it, but it's a file, not a folder (ENOTDIR).
  3. "Unknown": Something weird happened (Crash).

Step-by-Step Implementation

We handle errors in two places: the Validator (logic) and the UI (presentation).

Step 1: Catching the Crash

In Chapter 3: Directory Validation, we used stat() to check a file. If stat() fails, it throws an error. We need to catch that error immediately.

// --- File: validation.ts ---
import { getErrnoCode } from '../../utils/errors.js';

try {
  const stats = await stat(absolutePath);
  // ... check if directory ...
} catch (e: unknown) {
  // 1. Extract the cryptic error code (e.g., "ENOENT")
  const code = getErrnoCode(e);
  
  // Logic continues below...
}

Explanation:

Step 2: Categorizing the Error

Now that we have the code, we map it to our "Report Card" result types.

  // Inside the catch block...
  
  // 2. Check if it's a "Missing" or "Permission" error
  if (
    code === 'ENOENT' || // File not found
    code === 'EACCES'    // Permission denied
  ) {
    // 3. Return a safe failure result
    return {
      resultType: 'pathNotFound',
      directoryPath,
      absolutePath,
    };
  }

  // 4. If it's a weird error we don't know, let it crash.
  throw e;

Explanation:

Step 3: The "Translator" Function

Now we have a clean result object. We need a function to turn that object into human-readable text.

// --- File: validation.ts ---
import chalk from 'chalk';

export function addDirHelpMessage(result: AddDirectoryResult): string {
  switch (result.resultType) {
    case 'pathNotFound':
      return `Path ${chalk.bold(result.absolutePath)} was not found.`;
      
    case 'notADirectory':
      // We can be extra helpful here!
      const parent = dirname(result.absolutePath);
      return `${chalk.bold(result.directoryPath)} is not a directory. ` +
             `Did you mean ${chalk.bold(parent)}?`;
             
    // ... handle other cases
  }
}

Explanation:

Under the Hood: The Flow

How does a raw system error become a helpful message? Let's trace the path of a "Permission Denied" error.

sequenceDiagram participant OS as Operating System participant Val as Validator participant Trans as Translator participant UI as User Interface Note over OS: User selects secure folder OS-->>Val: Throws Error "EACCES" Note over Val: Categorization Val->>Val: Maps EACCES -> 'pathNotFound' Val-->>UI: Returns Result Object Note over UI: Presentation UI->>Trans: Calls addDirHelpMessage(Result) Trans-->>UI: Returns "Path was not found." UI-->>User: Displays formatted error

Internal Implementation Details

The Error UI Component

In Chapter 2: Interactive Command UI, we briefly mentioned <AddDirError />. Now let's see why it's special.

React (Ink) renders frames. If we print an error and immediately exit the process, the user might never see the text because the process dies too fast.

// --- File: add-dir.tsx ---

function AddDirError({ message, onDone }) {
  // 1. Wait for the UI to paint the error
  useEffect(() => {
    const timer = setTimeout(onDone, 0); // Brief delay
    return () => clearTimeout(timer);
  }, [onDone]);

  // 2. Render the message nicely
  return (
    <Box flexDirection="column">
      <MessageResponse>
        <Text>{message}</Text>
      </MessageResponse>
    </Box>
  );
}

Explanation:

Handling "Save" Failures

Sometimes validation passes, but saving to the hard drive fails (e.g., disk full). We handle this in the main command logic.

// --- File: add-dir.tsx ---

try {
  persistPermissionUpdate(permissionUpdate);
  message = `Added ${path} and saved to settings`;
} catch (error) {
  // Graceful degradation
  message = `Added ${path}, but failed to save settings: ${error.message}`;
}

Explanation:

Conclusion

Congratulations! You have completed the add-dir project tutorial.

In this final chapter, we built an Error Feedback System. We learned:

  1. How to catch and group technical error codes (ENOENT, EACCES) into logical categories.
  2. How to translate those categories into helpful, human-readable suggestions.
  3. How to ensure error messages are actually rendered before the CLI exits.

Project Summary

You have built a robust CLI command from scratch:

  1. Command Definition: You registered the command in the menu.
  2. Interactive Command UI: You built a flexible controller for user input.
  3. Directory Validation: You built a "Bouncer" to secure the input.
  4. State & Permission Management: You wired up the internal logic to grant access.
  5. Error Feedback System: You ensured the user is guided gently when things go wrong.

You now have a fully functional tool that safely manages workspace directories! Happy coding!


Generated by Code IQ