Stub Implementation Detection Guide
Overview
Stub detection automatically identifies incomplete, placeholder, or mock implementations in the codebase. This prevents accidental deployment of unfinished code and helps teams track what still needs to be completed.
What is a Stub?
A stub is a function or component that:
- Throws "not implemented" errors
- Returns placeholder values (null, empty objects, mock data)
- Contains TODO/FIXME comments indicating incomplete work
- Only logs to console without doing real work
- Has minimal/empty implementation
- Contains placeholder text in UI
Detection Methods
1. Pattern-Based Detection
Scans code for specific patterns that indicate stubs:
Error Throwing
// ❌ Detected as stub
export function processData(data) {
throw new Error('not implemented')
}
Console Logging Only
// ❌ Detected as stub
export function validateEmail(email) {
console.log('validating:', email) // Nothing else
}
Null/Undefined Returns
// ❌ Detected as stub
export function fetchData() {
return null
}
Placeholder Text
// ❌ Detected as stub
function Dashboard() {
return <div>TODO: Build dashboard</div>
}
Mock Data with Markers
// ❌ Detected as stub
export function getUsers() {
return [ // stub data
{ id: 1, name: 'John' }
]
}
2. Completeness Analysis
Analyzes implementation quality:
- Logical Lines: Actual code (excluding returns and comments)
- Return Lines: How many return statements
- JSX Lines: For components, how much actual UI
- Completeness Score: 0-100% based on implementation density
Scoring:
- 0%: Throws not implemented error
- 0-30%: Critical (only logging, returning null, no real logic)
- 30-60%: Medium (minimal implementation, mostly mock data)
- 60-80%: Low (mostly complete, some placeholders)
- 80-100%: Good (real implementation)
3. Code Indicators
Detects special markers:
| Indicator | Severity | Meaning |
|---|---|---|
throw new Error('not implemented') |
Critical | Explicitly unimplemented |
// TODO: or // FIXME: |
Medium | Known issue, incomplete |
console.log() only |
High | Debug logging, not real code |
// mock, // stub |
Medium | Explicitly marked placeholder |
return null |
Low | Empty return value |
<> </> |
High | Empty component fragment |
Workflow Integration
Automatic Detection
The detect-stubs.yml workflow runs:
- On every PR (to flag new stubs)
- On every push to main/master
- Weekly scheduled (Monday midnight)
PR Comments
Posts a summary comment showing:
- Total stubs found
- Severity breakdown
- Critical issues with file/line/function
- Recommendations for fixes
Example:
## 🔍 Stub Implementation Detection Report
### Summary
- Pattern-Based Stubs: 5
- Low Completeness Items: 3
- Average Completeness: 72%
### Severity Breakdown
- 🔴 Critical: 2
- 🟠 Medium: 2
- 🟡 Low: 1
### 🔴 Critical Issues Found
| File | Line | Function | Type |
|------|------|----------|------|
| src/api/users.ts | 42 | fetchUsers | throws-not-implemented |
| src/components/Dashboard.tsx | 15 | Dashboard | empty-fragment |
Local Usage
Run Detection Locally
# Pattern-based stub detection
npx tsx scripts/detect-stub-implementations.ts
# Completeness analysis
npx tsx scripts/analyze-implementation-completeness.ts
# Generate detailed report
npx tsx scripts/generate-stub-report.ts
# All three
npm run detect-stubs
Output Formats
All scripts output JSON for programmatic access:
Pattern Detection Output
{
"totalStubsFound": 5,
"bySeverity": {
"high": 2,
"medium": 2,
"low": 1
},
"byType": {
"not-implemented": 2,
"todo-comment": 1,
"console-log-only": 1,
"returns-empty-value": 1
},
"criticalIssues": [
{
"file": "src/api/users.ts",
"line": 42,
"function": "fetchUsers",
"type": "not-implemented"
}
]
}
Completeness Analysis Output
{
"totalAnalyzed": 45,
"bySeverity": {
"critical": 2,
"high": 5,
"medium": 8,
"low": 12
},
"flagTypes": {
"has-todo-comments": 5,
"throws-not-implemented": 2,
"only-console-log": 1
},
"averageCompleteness": 72.4,
"criticalStubs": [
{
"file": "src/api/users.ts",
"line": 42,
"name": "fetchUsers",
"type": "function",
"flags": ["throws-not-implemented"],
"summary": "Potential stub: throws-not-implemented"
}
]
}
Common Stub Patterns & Fixes
Pattern 1: Not Implemented Error
Problem: Function explicitly throws unimplemented error Severity: 🔴 Critical Fix: Implement the function
// ❌ Before
export async function fetchUserData(id: string) {
throw new Error('not implemented')
}
// ✅ After
export async function fetchUserData(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) throw new Error(`Failed to fetch user ${id}`)
return response.json()
}
Pattern 2: Console Logging Only
Problem: Function only logs without doing real work Severity: 🟠 High Fix: Replace logging with actual implementation
// ❌ Before
export function calculateTotal(items: Item[]): number {
console.log('calculating total for:', items)
// nothing else
}
// ✅ After
export function calculateTotal(items: Item[]): number {
return items.reduce((sum, item) => sum + item.price, 0)
}
Pattern 3: Return Null/Undefined
Problem: Function returns null or undefined Severity: 🟡 Medium Fix: Return actual data or use types to force implementation
// ❌ Before
export function getConfig() {
return null // TODO: load config
}
// ✅ After
export function getConfig(): Config {
return configLoader.load()
}
Pattern 4: Placeholder Component
Problem: Component renders placeholder text instead of UI Severity: 🟠 High Fix: Implement the component properly
// ❌ Before
export function Dashboard() {
return <div>TODO: Build dashboard</div>
}
// ✅ After
export function Dashboard() {
return (
<div className="dashboard">
<Header />
<Sidebar />
<MainContent />
</div>
)
}
Pattern 5: Mock Data
Problem: Function returns hardcoded mock data Severity: 🟠 Medium Fix: Replace with real data source
// ❌ Before
export function getUsers(): User[] {
return [ // mock data
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' }
]
}
// ✅ After
export async function getUsers(): Promise<User[]> {
const data = await Database.query('SELECT * FROM users')
return data.map(row => new User(row))
}
Pattern 6: TODO Comments
Problem: Code has TODO/FIXME comments indicating incomplete work Severity: 🟡 Medium/Low Fix: Create GitHub issue and remove TODO from code
// ❌ Before
export function validateEmail(email: string): boolean {
// TODO: Add real email validation
return true
}
// ✅ After (create issue #123 first)
export function validateEmail(email: string): boolean {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return emailRegex.test(email)
}
Pattern 7: Empty Component
Problem: Component has minimal or empty JSX Severity: 🟠 High Fix: Implement the component's UI
// ❌ Before
export function UserList() {
return <div></div>
}
// ✅ After
export function UserList() {
const users = useQuery('users')
return (
<div className="user-list">
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
)
}
Best Practices
1. Never Leave Stubs in Main Branch
# Before merging, ensure no stubs in changed files
git diff HEAD~1 -- 'src/**/*.ts' | grep -i 'todo\|not implemented'
2. Use Types to Force Implementation
// ❌ Function can return anything
function getValue() {
// oops, forgot to implement
}
// ✅ Type forces implementation
function getValue(): string {
// TypeScript error: missing return
// MUST implement
}
3. Create Issues Instead of TODOs
// ❌ Don't do this
function processData(data) {
// TODO: add caching (#TBD)
return compute(data)
}
// ✅ Do this
// Implemented cache per issue #456
const cache = new LRUCache()
function processData(data) {
return cache.getOrCompute(data, () => compute(data))
}
4. Test Stubs Explicitly
// Make stubs fail tests explicitly
describe('getUsers', () => {
it('should fetch users from API', async () => {
// This WILL fail if implementation is missing
const users = await getUsers()
expect(users).toBeDefined()
expect(users.length).toBeGreaterThan(0)
expect(users[0].name).toBeDefined()
})
})
5. Use Linting to Prevent Stubs
Add ESLint rules to .eslintrc.json:
{
"rules": {
"no-console": ["error", { "allow": ["warn", "error"] }],
"no-throw-literal": "error",
"no-empty-function": ["error", { "allow": ["arrowFunctions"] }]
}
}
Interpreting the Report
Severity Levels
-
🔴 Critical (Completeness: 0%)
- Blocks production
- Must fix immediately
- Examples:
throw new Error('not implemented')
-
🟠 High (Completeness: 10-30%)
- Should fix before merge
- Likely causes bugs
- Examples: Console logging only, empty components
-
🟡 Medium (Completeness: 40-70%)
- Should fix soon
- Partial implementation
- Examples: Mock data, basic structure
-
🟢 Low (Completeness: 80-99%)
- Nice to fix
- Mostly complete
- Examples: Minor TODOs, edge cases
Metrics Explained
| Metric | Meaning |
|---|---|
| Logical Lines | Lines that do actual work (not returns/comments) |
| Return Lines | Number of return statements |
| JSX Lines | For components, lines rendering UI |
| Completeness | Estimated % of implementation done |
| Flags | Detected stub indicators |
Artifacts
The workflow uploads three artifacts:
- stub-patterns.json - Raw pattern detection data
- implementation-analysis.json - Completeness scoring
- stub-report.md - Formatted markdown report
- changed-stubs.txt - Stubs in changed files (PRs only)
Available for 30 days after workflow run.
CI/CD Integration
Failing Builds
The workflow runs with continue-on-error: true, so stubs don't block merging. However, you can:
- Enable stricter linting to fail on TODOs
- Require test coverage (which fails with stubs)
- Use branch protection rules to require review of detected stubs
GitHub Checks
- Posts check run with stub detection results
- Shows in PR checks section
- Includes summary of critical issues
Troubleshooting
"No stubs found" but code looks incomplete
- Patterns may not match your specific style
- Check individual function with completeness analyzer
- Consider adding custom patterns to detection script
Too many false positives
- Edit
STUB_PATTERNSindetect-stub-implementations.ts - Adjust completeness thresholds in
analyze-implementation-completeness.ts - Add file/function exclusions
Stubs not showing in PR comment
- Check workflow permissions (needs
pull-requests: write) - Verify GitHub API isn't rate limited
- Check workflow logs for errors
Extension Points
Add Custom Patterns
Edit scripts/detect-stub-implementations.ts:
const STUB_PATTERNS = [
// ... existing patterns
{
name: 'Your custom pattern',
pattern: /your regex here/,
type: 'custom-stub',
severity: 'high',
description: 'Your description'
}
]
Add Custom Analysis
Create new script in scripts/:
npx tsx scripts/my-custom-analysis.ts > my-report.json
Then add to workflow in .github/workflows/detect-stubs.yml.
References
Last updated: December 25, 2025