Claude Code Plugins

Community-maintained marketplace

Feedback

|

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name sentry-known-pitfalls
description Common Sentry pitfalls and how to avoid them. Use when troubleshooting Sentry issues, reviewing configurations, or preventing common mistakes. Trigger with phrases like "sentry mistakes", "sentry pitfalls", "sentry common issues", "sentry anti-patterns".
allowed-tools Read, Write, Edit, Grep
version 1.0.0
license MIT
author Jeremy Longshore <jeremy@intentsolutions.io>

Sentry Known Pitfalls

Overview

Common mistakes and anti-patterns when using Sentry, and how to avoid them.

SDK Initialization Pitfalls

Pitfall 1: Late Initialization

// ❌ BAD: Errors before init() are lost
app.use(errorHandler);
Sentry.init({ dsn: process.env.SENTRY_DSN });

// ✅ GOOD: Initialize first
Sentry.init({ dsn: process.env.SENTRY_DSN });
app.use(errorHandler);

Pitfall 2: Multiple Initializations

// ❌ BAD: Multiple init() calls cause issues
// file1.ts
Sentry.init({ dsn: 'dsn1' });

// file2.ts
Sentry.init({ dsn: 'dsn2' }); // Overwrites first!

// ✅ GOOD: Single initialization point
// sentry.ts
export function initSentry() {
  if (!Sentry.getCurrentHub().getClient()) {
    Sentry.init({ dsn: process.env.SENTRY_DSN });
  }
}

Pitfall 3: Wrong SDK for Framework

// ❌ BAD: Generic SDK for framework
import * as Sentry from '@sentry/node'; // In Next.js app

// ✅ GOOD: Framework-specific SDK
import * as Sentry from '@sentry/nextjs'; // Next.js
import * as Sentry from '@sentry/react'; // React
import * as Sentry from '@sentry/vue'; // Vue

Error Capture Pitfalls

Pitfall 4: Swallowing Errors

// ❌ BAD: Error captured but swallowed
try {
  await riskyOperation();
} catch (error) {
  Sentry.captureException(error);
  // Error swallowed - app continues incorrectly
}

// ✅ GOOD: Capture and handle appropriately
try {
  await riskyOperation();
} catch (error) {
  Sentry.captureException(error);
  throw error; // Or handle properly
}

Pitfall 5: Capturing Non-Errors

// ❌ BAD: Capturing strings instead of errors
Sentry.captureException('Something went wrong'); // No stack trace!

// ✅ GOOD: Capture actual Error objects
Sentry.captureException(new Error('Something went wrong'));

// Or use captureMessage for non-errors
Sentry.captureMessage('Something happened', 'info');

Pitfall 6: Double Capture

// ❌ BAD: Capturing same error multiple times
app.use((err, req, res, next) => {
  Sentry.captureException(err);
  next(err);
});
app.use(Sentry.Handlers.errorHandler()); // Captures again!

// ✅ GOOD: Single capture point
app.use(Sentry.Handlers.errorHandler()); // Only this

Configuration Pitfalls

Pitfall 7: Hardcoded DSN

// ❌ BAD: DSN in code
Sentry.init({
  dsn: 'https://abc123@sentry.io/123', // Exposed!
});

// ✅ GOOD: Environment variable
Sentry.init({
  dsn: process.env.SENTRY_DSN,
});

Pitfall 8: 100% Sampling in Production

// ❌ BAD: Full sampling = huge bills
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 1.0, // 100% of all requests!
});

// ✅ GOOD: Production-appropriate rates
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
});

Pitfall 9: Ignoring beforeSend Return

// ❌ BAD: Not returning event
Sentry.init({
  beforeSend(event) {
    console.log('Event:', event);
    // Forgot to return! Event is dropped.
  },
});

// ✅ GOOD: Always return event (or null to drop)
Sentry.init({
  beforeSend(event) {
    console.log('Event:', event);
    return event; // Don't forget!
  },
});

Performance Pitfalls

Pitfall 10: Not Finishing Transactions

// ❌ BAD: Transaction never finished
const transaction = Sentry.startTransaction({ name: 'operation' });
await doWork();
// Forgot transaction.finish()!

// ✅ GOOD: Always finish with try/finally
const transaction = Sentry.startTransaction({ name: 'operation' });
try {
  await doWork();
} finally {
  transaction.finish();
}

Pitfall 11: Orphan Spans

// ❌ BAD: Spans without transaction context
const span = Sentry.startSpan({ name: 'work' }); // No parent!

// ✅ GOOD: Spans within transaction
const transaction = Sentry.startTransaction({ name: 'operation' });
Sentry.getCurrentHub().configureScope((scope) => scope.setSpan(transaction));

const span = transaction.startChild({ op: 'work' });
// Now properly linked

Source Maps Pitfalls

Pitfall 12: Wrong URL Prefix

# ❌ BAD: Prefix doesn't match actual URLs
sentry-cli releases files $VERSION upload-sourcemaps ./dist
# Files uploaded as ~/dist/main.js
# But browser loads from /static/js/main.js

# ✅ GOOD: Match actual URL structure
sentry-cli releases files $VERSION upload-sourcemaps ./dist \
  --url-prefix "~/static/js"

Pitfall 13: Release Version Mismatch

// ❌ BAD: SDK and CLI use different versions
// SDK: release: 'v1.0.0'
// CLI: sentry-cli releases new '1.0.0' (no 'v' prefix)

// ✅ GOOD: Consistent versioning
const VERSION = process.env.GIT_SHA;
Sentry.init({ release: VERSION });
// CLI: sentry-cli releases new $GIT_SHA

Integration Pitfalls

Pitfall 14: Missing Request Handler

// ❌ BAD: Error handler without request handler
app.use(Sentry.Handlers.errorHandler());
// Missing request context!

// ✅ GOOD: Both handlers in correct order
app.use(Sentry.Handlers.requestHandler());
// ... routes ...
app.use(Sentry.Handlers.errorHandler());

Pitfall 15: Blocking Event Sending

// ❌ BAD: Awaiting Sentry in request path
app.post('/api/data', async (req, res) => {
  try {
    const result = await processData(req.body);
    res.json(result);
  } catch (error) {
    await Sentry.captureException(error); // Blocks response!
    await Sentry.flush(5000); // Even more blocking!
    res.status(500).json({ error: 'Failed' });
  }
});

// ✅ GOOD: Non-blocking capture
app.post('/api/data', async (req, res) => {
  try {
    const result = await processData(req.body);
    res.json(result);
  } catch (error) {
    Sentry.captureException(error); // Fire and forget
    res.status(500).json({ error: 'Failed' });
  }
});

Monitoring Pitfalls

Pitfall 16: Alert Fatigue

# ❌ BAD: Alert on every error
alert_rules:
  - condition: any_error
    action: email_team  # Hundreds of emails!

# ✅ GOOD: Threshold-based alerts
alert_rules:
  - condition: error_rate > 5%
    action: slack_warning
  - condition: error_rate > 20%
    action: pagerduty_critical

Pitfall 17: Ignoring Release Health

// ❌ BAD: No release tracking
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  // No release specified
});

// ✅ GOOD: Track releases
Sentry.init({
  dsn: process.env.SENTRY_DSN,
  release: `myapp@${process.env.GIT_SHA}`,
  autoSessionTracking: true,
});

Checklist: Avoid These Pitfalls

## SDK Setup
- [ ] Initialize Sentry before app starts
- [ ] Use framework-specific SDK
- [ ] Single initialization point
- [ ] DSN in environment variable

## Error Handling
- [ ] Capture Error objects, not strings
- [ ] Single capture point (no duplicates)
- [ ] Re-throw or handle after capture
- [ ] Return event from beforeSend

## Performance
- [ ] Production-appropriate sample rates
- [ ] Finish all transactions
- [ ] Non-blocking captures
- [ ] Spans attached to transactions

## Source Maps
- [ ] Correct URL prefix
- [ ] Matching release versions
- [ ] Upload in CI/CD

## Monitoring
- [ ] Threshold-based alerts
- [ ] Release tracking enabled
- [ ] Environment tags

Resources