expiring-todo-comments
ESLint rule documentation for expiring-todo-comments
๐ก Live from GitHub โ This documentation is fetched directly from expiring-todo-comments.md and cached for 6 hours.
Keywords: TODO, FIXME, XXX, expiration, comments, technical debt, code quality, ESLint rule, version, date, LLM-optimized
Add expiration conditions to TODO comments to prevent forgotten tasks. This rule is part of eslint-plugin-conventions and provides LLM-optimized error messa
Add expiration conditions to TODO comments to prevent forgotten tasks. This rule is part of eslint-plugin-conventions and provides LLM-optimized error messages.
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Warning (code quality) |
| Auto-Fix | โ No (requires addressing the TODO) |
| Category | Quality |
| ESLint MCP | โ Optimized for ESLint MCP integration |
| Best For | Teams tracking technical debt, version-based deprecations |
Rule Details
Why This Matters
| Issue | Impact | Solution |
|---|---|---|
| ๐ Forgotten TODOs | Technical debt accumulates | Add expiration dates |
| ๐ Version Migration | Old workarounds stay | Version-based conditions |
| ๐ฆ Dependency Updates | Polyfills become unnecessary | Package-based conditions |
| โฐ Deadline Tracking | Tasks slip through reviews | Date-based conditions |
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
terms | string[] | ['TODO', 'FIXME', 'XXX'] | Terms to check for |
dateFormat | string | 'YYYY-MM-DD' | Date format for expiry dates |
Condition Types
| Condition Type | Format | Example |
|---|---|---|
| Date | [YYYY-MM-DD] | TODO [2025-01-01]: Remove this |
| Package Version | [>=X.Y.Z] | TODO [>=2.0.0]: Use new API |
| Engine Version | [engine:node@>=X] | TODO [engine:node@>=20]: Use fetch |
| Dependency | [+package] / [-package] | TODO [+lodash]: Replace with lodash |
Examples
โ Expired (Will Report)
// Date-based expiration (if current date >= 2024-12-01)
// TODO [2024-12-01]: Remove deprecated API call
fetchLegacyData();
// Version-based expiration (if package.json version >= 2.0.0)
// FIXME [>=2.0.0]: Migrate to new authentication system
useOldAuth();
// Engine-based expiration (if node >= 20)
// TODO [engine:node@>=20]: Replace node-fetch with native fetch
import fetch from 'node-fetch';
// Dependency-based (if lodash is installed)
// TODO [+lodash]: Use _.debounce instead
function debounce() { /* custom impl */ }โ Not Yet Expired
// Future date
// TODO [2030-01-01]: Consider removing this feature
legacyFeature();
// Future version
// FIXME [>=10.0.0]: This will need updating
currentImplementation();โ Invalid Format
// Missing brackets
// TODO 2024-12-01: Fix this // โ Invalid
// Wrong date format
// TODO [12/01/2024]: Fix this // โ Invalid
// Multiple conditions
// TODO [2024-01-01, >=2.0.0]: Fix this // โ InvalidConfiguration Examples
Basic Usage
{
rules: {
'conventions/expiring-todo-comments': 'warn'
}
}Custom Terms
{
rules: {
'conventions/expiring-todo-comments': ['warn', {
terms: ['TODO', 'FIXME', 'XXX', 'HACK', 'BUG']
}]
}
}Strict Mode
{
rules: {
'conventions/expiring-todo-comments': ['error', {
terms: ['TODO', 'FIXME']
}]
}
}Use Cases
Version Migrations
// When you're waiting for a major version to remove compatibility code
// TODO [>=3.0.0]: Remove React 17 compatibility layer
if (React.version.startsWith('17')) {
// legacy code
}Node.js Feature Adoption
// Waiting for minimum Node version in CI
// TODO [engine:node@>=18]: Use native fetch instead of node-fetch
import fetch from 'node-fetch';
// TODO [engine:node@>=20]: Use native test runner
import { describe, it } from 'node:test';Scheduled Deprecations
// Time-boxed technical debt
// TODO [2025-06-01]: Remove this after Q2 migration
function legacyApiHandler() { }Dependency Additions
// Waiting for a package to be added
// TODO [+zod]: Replace with zod validation
function validateManually(data: unknown) { }When Not To Use
| Scenario | Recommendation |
|---|---|
| ๐ Regular TODOs | This rule only affects conditional TODOs |
| ๐ No release cycle | Date conditions work without versions |
| ๐งช Prototyping | Disable during rapid development |
Comparison with Alternatives
| Feature | expiring-todo-comments | unicorn rule | Manual tracking |
|---|---|---|---|
| Date conditions | โ Yes | โ Yes | โ No |
| Version conditions | โ Yes | โ Yes | โ No |
| Engine conditions | โ Yes | โ Yes | โ No |
| LLM-Optimized | โ Yes | โ No | โ No |
| ESLint MCP | โ Optimized | โ No | โ No |
Related Rules
no-commented-code- Prevents commented-out codecognitive-complexity- Code complexity limits
Further Reading
- unicorn expiring-todo-comments - Unicorn implementation
- Managing Technical Debt - Martin Fowler on tech debt
- ESLint MCP Setup - Enable AI assistant integration
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Dynamic Variable References
Why: Static analysis cannot trace values stored in variables or passed through function parameters.
// โ NOT DETECTED - Value from variable
const value = externalSource();
processValue(value); // Variable origin not trackedMitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.
Imported Values
Why: When values come from imports, the rule cannot analyze their origin or construction.
// โ NOT DETECTED - Value from import
import { getValue } from './helpers';
processValue(getValue()); // Cross-file not trackedMitigation: Ensure imported values follow the same constraints. Use TypeScript for type safety.