# nx-troubleshooting

> Generic troubleshooting engine for matching errors to solutions

Latest version **2.0.1** (published 2025-12-04) · ISC license · 0 weekly downloads

## Install

```sh
npm install nx-troubleshooting
pnpm add nx-troubleshooting
yarn add nx-troubleshooting
bun add nx-troubleshooting
```

## Health

**Score 55/100 (C)** — status: stable.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

## Facts

| | |
|---|---|
| Version | 2.0.1 |
| Published | 2025-12-04 |
| First published | 2025-12-02 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 71.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | nx-morpheus |
| Keywords | troubleshooting, errors, diagnostics, nx |

## Links

- npm: https://www.npmjs.com/package/nx-troubleshooting
- Repository: https://github.com/nx-intelligence/nx-troubleshooting
- Homepage: https://github.com/nx-intelligence/nx-troubleshooting#readme
- Issues: https://github.com/nx-intelligence/nx-troubleshooting/issues
- npm.io page: https://npm.io/package/nx-troubleshooting

## Dependencies (1)

- [nx-config2](https://npm.io/package/nx-config2.md) ^1.0.0 || ^2.0.0 || ^3.0.0

## Alternatives

- [@sentry/react-native](https://npm.io/package/@sentry/react-native.md) — 2.6M weekly downloads
- [@ardatan/aggregate-error](https://npm.io/package/@ardatan/aggregate-error.md) — 708.1K weekly downloads
- [custom-error-generator](https://npm.io/package/custom-error-generator.md) — 2.0K weekly downloads
- [@technik-sde/prosemirror-recreate-transform](https://npm.io/package/@technik-sde/prosemirror-recreate-transform.md) — 1.5K weekly downloads
- [@suchipi/error-utils](https://npm.io/package/@suchipi/error-utils.md) — 78 weekly downloads

## Recent versions

- 2.0.1 (latest) — 2025-12-04
- 1.0.0 — 2025-12-02

## README

# nx-troubleshooting

> Generic troubleshooting engine for matching errors to solutions

[![npm version](https://img.shields.io/npm/v/nx-troubleshooting.svg)](https://www.npmjs.com/package/nx-troubleshooting)
[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)

`nx-troubleshooting` is a generic, reusable npm package that provides intelligent error-to-solution matching for any Node.js/TypeScript project. It loads troubleshooting narratives from JSON files, matches errors to relevant solutions based on configurable symptoms, and formats helpful guidance for developers.

## Features

- 🎯 **Intelligent Error Matching** - Matches errors to solutions using multiple strategies (error name, keywords, symptom evaluation)
- 🔍 **Flexible Probe System** - Built-in probes plus extensible custom probes for project-specific checks
- 📝 **Template Variables** - Dynamic solution messages with `{{variable}}` syntax and nested access
- 📊 **Multiple Output Formats** - Markdown, JSON, and plain text formatting
- 🛠️ **Generic Probe Toolbox** - Additional probes for common scenarios (file system, environment, config types)
- 🔌 **Framework Agnostic** - Works with any Node.js/TypeScript project
- 📦 **Zero Dependencies** - Only uses Node.js built-ins (plus optional `nx-config2` for enhanced features)

## Installation

```bash
npm install nx-troubleshooting
```

## Quick Start

```typescript
import { TroubleshootingEngine } from 'nx-troubleshooting';

// Initialize engine
const engine = new TroubleshootingEngine({
  narrativesPath: './metadata/troubleshooting.json'
});

// Load narratives
await engine.loadNarratives();

// Match an error
const error = new Error('Missing connections configuration');
const matches = await engine.matchError(error, {
  error,
  config: { /* your config */ },
  query: { /* your query */ }
});

// Format results
const markdown = engine.formatMatches(matches, 'markdown');
console.log(markdown);
```

## Core Concepts

### Troubleshooting Narrative

A troubleshooting narrative is a structured description of a problem and its solution:

```typescript
{
  id: "missing-connections-config",
  title: "Missing Connections Configuration",
  description: "The application config is missing the required 'connections' object...",
  symptoms: [
    {
      probe: "config-check",
      params: { field: "connections" },
      condition: "result.exists == false"
    }
  ],
  solution: [
    {
      type: "code",
      message: "Add a 'connections' object to your config:",
      code: "{\n  \"connections\": { ... }\n}"
    }
  ]
}
```

### Symptoms

Symptoms define how to detect a problem using **probes**:

- **Probe**: A function that checks a condition (e.g., `config-check`, `file-exists`)
- **Params**: Parameters passed to the probe
- **Condition**: JavaScript expression evaluated against the probe result

### Solutions

Solutions provide guidance on how to resolve the issue:

- **Type**: Solution type (e.g., `collaborate`, `link`, `code`)
- **Message**: Solution message (supports template variables)
- **URL**: Optional URL for `link` type solutions
- **Code**: Optional code example for `code` type solutions

## API Reference

### TroubleshootingEngine

Main class that handles loading narratives and matching errors.

```typescript
class TroubleshootingEngine {
  constructor(options?: {
    narrativesPath?: string;           // Path to JSON file or directory
    customProbes?: ProbeRegistry;       // Custom probe functions
    templateVars?: Record<string, any>; // Default template variables
    envPrefix?: string;                 // Environment variable prefix
  });

  // Load narratives from JSON file(s)
  loadNarratives(path?: string): Promise<void>;
  
  // Load narratives from in-memory array
  loadNarrativesFromArray(narratives: TroubleshootingNarrative[]): void;
  
  // Match an error to relevant narratives
  matchError(error: Error, context?: ErrorContext): Promise<TroubleshootingMatch[]>;
  
  // Match based on custom criteria
  match(context: MatchContext): Promise<TroubleshootingMatch[]>;
  
  // Format matched narratives for display
  formatMatches(matches: TroubleshootingMatch[], format?: 'markdown' | 'json' | 'text'): string;
  
  // Get all loaded narratives
  getNarratives(): TroubleshootingNarrative[];
  
  // Get narrative by ID
  getNarrative(id: string): TroubleshootingNarrative | undefined;
  
  // Register a custom probe
  registerProbe(name: string, probe: ProbeFunction): void;
  
  // Get current probe registry
  getProbeRegistry(): ProbeRegistry;
}
```

## Built-in Probes

The package provides several built-in probes:

### `error-message`

Check if error message contains keywords:

```typescript
{
  probe: "error-message",
  params: { keywords: ["missing", "connection"] },
  condition: "result.matches == true"
}
```

### `error-name`

Check if error name matches:

```typescript
{
  probe: "error-name",
  params: { name: "ValidationError" },
  condition: "result.matches == true"
}
```

### `config-check`

Check if config field exists:

```typescript
{
  probe: "config-check",
  params: { field: "connections.database", required: true },
  condition: "result.exists == false"
}
```

### `file-exists`

Check if file exists:

```typescript
{
  probe: "file-exists",
  params: { path: "./config.json" },
  condition: "result.exists == false"
}
```

## Generic Probe Toolbox

Additional probes available via `probeToolbox`:

### `fs-path-status`

Check file system path status:

```typescript
import { probeToolbox } from 'nx-troubleshooting';

engine.registerProbe('fs-path-status', probeToolbox['fs-path-status']);

// Usage in narrative:
{
  probe: "fs-path-status",
  params: { targetPath: "./config.json" },
  condition: "result.exists == false || result.isDirectory == true"
}
```

### `env-runtime-info`

Get Node.js runtime information:

```typescript
{
  probe: "env-runtime-info",
  params: {},
  condition: "result.nodeVersion.startsWith('v18') == false"
}
```

### `env-var-check`

Check environment variable:

```typescript
{
  probe: "env-var-check",
  params: { name: "DATABASE_URL", requireNonEmpty: true },
  condition: "result.exists == false || result.nonEmpty == false"
}
```

### `config-field-type`

Check config field type:

```typescript
{
  probe: "config-field-type",
  params: { field: "port", type: "number" },
  condition: "result.exists == false || result.typeMatches == false"
}
```

## Custom Probes

Register project-specific probes:

```typescript
const engine = new TroubleshootingEngine({
  customProbes: {
    'mongodb-connect': async (params, context) => {
      try {
        const client = await MongoClient.connect(params.uri);
        await client.close();
        return { ok: true };
      } catch (error) {
        return { ok: false, error: error.message };
      }
    },
    'binding-check': (params, context) => {
      const bindings = context.config?.bindings || [];
      const found = bindings.some(b => b.connection === params.bindingConnection);
      return { found };
    }
  }
});

// Or register after construction:
engine.registerProbe('custom-probe', (params, context) => {
  // Your custom logic
  return { result: 'value' };
});
```

## Template Variables

Solution messages support template variables using `{{variable}}` syntax:

```json
{
  "message": "Your config is missing '{{query.binding.connection}}'. Available: {{availableConnections}}"
}
```

Template variables are resolved from:
1. `ErrorContext` properties
2. Custom `templateVars` passed to constructor
3. Probe results (via `result.*`)
4. Nested object access (e.g., `query.binding.connection`)

### Fallback Values

Use `||` for fallbacks:

```json
{
  "message": "Port: {{config.port||3000}}"
}
```

## Finding and Creating Troubleshooting Narratives

### Where to Find Existing Narratives

1. **Error Logs & Stack Traces**
   - Review production error logs
   - Check test failures
   - Analyze user-reported issues

2. **Common Error Patterns**
   - Configuration errors
   - Missing dependencies
   - Connection failures
   - Validation errors

3. **Support Tickets**
   - Frequently asked questions
   - Common user mistakes
   - Setup issues

4. **Code Review**
   - Error handling patterns
   - Validation logic
   - Configuration requirements

### How to Create a Troubleshooting Narrative

#### Step 1: Identify the Problem

Start with a real error scenario:

```typescript
// Error: "Missing connections configuration"
// Stack trace shows: ConfigError at line 42
// Context: config.connections is undefined
```

#### Step 2: Define Symptoms

Think about what conditions indicate this problem:

```json
{
  "symptoms": [
    {
      "probe": "config-check",
      "params": { "field": "connections" },
      "condition": "result.exists == false"
    },
    {
      "probe": "error-message",
      "params": { "keywords": ["missing", "connections", "configuration"] },
      "condition": "result.matches == true"
    }
  ]
}
```

#### Step 3: Write the Solution

Provide clear, actionable steps:

```json
{
  "solution": [
    {
      "type": "code",
      "message": "Add a 'connections' object to your configuration file:",
      "code": "{\n  \"connections\": {\n    \"database\": {\n      \"mongo\": [{\n        \"alias\": \"my-mongo\",\n        \"uri\": \"mongodb://localhost:27017\",\n        \"db\": \"mydb\"\n      }]\n    }\n  }\n}"
    },
    {
      "type": "link",
      "message": "See the configuration documentation for more details:",
      "url": "https://docs.example.com/configuration"
    }
  ]
}
```

#### Step 4: Complete the Narrative

```json
{
  "id": "missing-connections-config",
  "title": "Missing Connections Configuration",
  "description": "The application configuration is missing the required 'connections' object. This object defines database connections and other external service endpoints.",
  "possibleSolution": "Add a 'connections' object to your config file with at least one database connection.",
  "symptoms": [
    {
      "probe": "config-check",
      "params": { "field": "connections" },
      "condition": "result.exists == false"
    }
  ],
  "solution": [
    {
      "type": "code",
      "message": "Add a 'connections' object to your configuration:",
      "code": "{\n  \"connections\": {\n    \"database\": { ... }\n  }\n}"
    }
  ]
}
```

### Best Practices for Narratives

1. **Use Descriptive IDs**
   - Format: `kebab-case`
   - Example: `missing-connections-config`, `invalid-api-key`

2. **Clear Titles**
   - Be specific and concise
   - Example: "Missing Connections Configuration" not "Config Error"

3. **Detailed Descriptions**
   - Explain what the problem is
   - Include context about when it occurs
   - Example: "The application configuration is missing the required 'connections' object. This typically occurs during initial setup or when the config file is incomplete."

4. **Multiple Symptoms**
   - Use multiple probes for better matching
   - Combine error message keywords with config checks
   - Example: Check both error message AND config state

5. **Actionable Solutions**
   - Provide step-by-step guidance
   - Include code examples when relevant
   - Link to documentation
   - Use template variables for dynamic content

6. **Test Your Narratives**
   ```typescript
   const testError = new Error('Missing connections configuration');
   const matches = await engine.matchError(testError, {
     error: testError,
     config: {} // Missing connections
   });
   console.assert(matches.length > 0, 'Narrative should match');
   console.assert(matches[0].confidence > 0.5, 'Should have reasonable confidence');
   ```

## Example Troubleshooting JSON

See `examples/troubleshooting.json` for a complete example with multiple narratives demonstrating best practices.

## Environment Configuration

The engine supports environment-based configuration via `nx-config2`:

```bash
# Set narratives path
export NX_TROUBLE_NARRATIVES_PATH=./metadata/troubleshooting.json
```

Or configure programmatically:

```typescript
const engine = new TroubleshootingEngine({
  envPrefix: 'MY_APP',
  narrativesPath: './troubleshooting.json'
});
```

## Integration Examples

### In a Test Framework

```typescript
async function generateBugReport(error: Error, context: ErrorContext) {
  const engine = new TroubleshootingEngine({
    narrativesPath: './metadata/troubleshooting.json'
  });
  await engine.loadNarratives();
  
  const matches = await engine.matchError(error, context);
  const troubleshooting = engine.formatMatches(matches, 'markdown');
  
  return {
    error: {
      name: error.name,
      message: error.message,
      stack: error.stack
    },
    context,
    troubleshooting
  };
}
```

### In an Express Error Handler

```typescript
import { TroubleshootingEngine } from 'nx-troubleshooting';

const engine = new TroubleshootingEngine({
  narrativesPath: './troubleshooting.json'
});
await engine.loadNarratives();

app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  engine.matchError(err, {
    error: err,
    config: app.get('config'),
    query: req.query,
    operation: req.method
  }).then(matches => {
    const troubleshooting = engine.formatMatches(matches, 'markdown');
    res.status(500).json({
      error: err.message,
      troubleshooting
    });
  });
});
```

### With Custom Probes and Template Variables

```typescript
const engine = new TroubleshootingEngine({
  narrativesPath: './troubleshooting.json',
  customProbes: {
    'database-connection': async (params, context) => {
      // Check database connection
      return { connected: true, latency: 42 };
    }
  },
  templateVars: {
    supportEmail: 'support@example.com',
    documentationUrl: 'https://docs.example.com'
  }
});

// Narratives can use {{supportEmail}} and {{documentationUrl}}
```

## Output Formats

### Markdown

```markdown
## 🔧 Troubleshooting Help

### 1. Missing Connections Configuration

The application configuration is missing the required 'connections' object...

**Quick hint**: Add a 'connections' object to your config file

**Suggested steps:**
- (code) Add a 'connections' object to your configuration:

```json
{
  "connections": {
    "database": { ... }
  }
}
```
```

### JSON

```json
{
  "matches": [
    {
      "narrative": { /* full narrative */ },
      "confidence": 0.9,
      "matchedSymptoms": [ /* matched symptoms */ ],
      "context": { /* matching context */ }
    }
  ]
}
```

### Text

```
(1) Missing Connections Configuration [90%]
The application configuration is missing the required 'connections' object...
Hint: Add a 'connections' object to your config file
- code: Add a 'connections' object to your configuration:
```

## Matching Algorithm

The engine matches errors using:

1. **Error Name Matching** - Exact match with narrative ID or title (confidence: 1.0)
2. **Keyword Matching** - Keywords from error message matched against narrative title/description (confidence: 0.7-0.9)
3. **Symptom Evaluation** - All symptoms evaluated, confidence based on match ratio (confidence: 0.5-0.8)
4. **Sorting** - Results sorted by confidence (highest first)

## TypeScript Support

Full TypeScript definitions are included:

```typescript
import {
  TroubleshootingEngine,
  TroubleshootingNarrative,
  ErrorContext,
  MatchContext,
  TroubleshootingMatch,
  ProbeFunction,
  ProbeRegistry
} from 'nx-troubleshooting';
```

## Contributing

Contributions are welcome! Please see the [contributing guide](CONTRIBUTING.md) for details.

## License

ISC

## Related Packages

- [`nx-config2`](https://www.npmjs.com/package/nx-config2) - Configuration management (used for env config)

---

**Made with ❤️ by nx-intelligence**

---
_Source: https://npm.io/package/nx-troubleshooting · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
