Skip to content

Fix: SWC Build Corruption from Duplicate .ts/.js Files #831

@dshep

Description

@dshep

Problem Summary

SWC build corruption caused MCP server startup failures and syntax errors in compiled JavaScript files. Root cause: 10 duplicate TypeScript files that were never imported, confusing SWC's sourcemap generator during batch compilation.

Symptoms

MCP Server Failure:

SyntaxError: Invalid or unexpected token
    at compileSourceTextModule (node:internal/modules/esm/utils:346:16)

file:///path/to/dist-cjs/src/cli/simple-cli.js:2978
# 2. Design architecture
^

Build Corruption Pattern:

//# sourceMappingURL=simple-cli.js.map sparc run spec-pseudocode "..."

# 2. Design architecture
npx claude-flow sparc run architect "..."

Sourcemap URLs were concatenated with bash script content from duplicate files.

Root Cause Analysis

What Happened

  1. Incomplete TypeScript Migration (July 17, 2025)

    • Developer created .ts versions of 9 files with type annotations
    • Forgot to update imports to reference .ts files
    • Forgot to delete original .js files
    • Result: Both versions committed, but only .js versions imported
  2. Import Evidence:

// ALL imports referenced .js, even from TypeScript files:
import { HelpFormatter } from './help-formatter.js';  // ✅ Used

// NOBODY imported .ts:
import { HelpFormatter } from './help-formatter.ts';  // ❌ Never happened
  1. SWC Confusion During Batch Compilation:
    • SWC processed both file.js AND file.ts
    • Both tried to output to same location
    • Sourcemap generator mixed code fragments from both files
    • Only manifested during batch builds with sourcemaps enabled
    • Single file compilation worked fine (hidden bug)

Files Affected

9 duplicate files that should be removed (never imported, dead code):

File Lines Added Status
src/cli/help-formatter.ts 183 Jul 17, 2025 ❌ Never imported
src/cli/simple-cli.ts ~3,400 Oct 15, 2025 ❌ Never imported
src/cli/simple-commands/agent.ts Unknown Unknown ❌ Never imported
src/cli/simple-commands/config.ts Unknown Unknown ❌ Never imported
src/cli/validation-helper.ts Unknown Unknown ❌ Never imported
src/core/version.ts Unknown Unknown ❌ Never imported
src/memory/swarm-memory.ts Unknown Unknown ❌ Never imported
src/utils/error-handler.ts Unknown Unknown ❌ Never imported
src/utils/key-redactor.ts Unknown Unknown ❌ Never imported
src/utils/metrics-reader.ts Unknown Unknown ❌ Never imported

Were .js and .ts Logically Equivalent?

YES - The .ts versions had:

  • ✅ Type annotations (: string, : CommandInfo)
  • ✅ Interface definitions
  • ✅ Access modifiers (private, readonly)
  • Otherwise IDENTICAL logic

Example:

// .ts version (never imported)
export interface CommandInfo {
  name: string;
  description: string;
}

export class HelpFormatter {
  private static readonly INDENT = '    ';
  static formatHelp(info: CommandInfo): string { ... }
}

// .js version (actually used)
export class HelpFormatter {
  static INDENT = '    ';
  static formatHelp(info) { ... }  // Same logic, no types
}

Proposed Fix

Remove the 9 duplicate .ts files listed above.

Expected Impact:

  • ✅ Build will reduce from 586 to ~577 files
  • ✅ Remove ~5,000+ lines of dead code
  • ✅ MCP server will start successfully
  • ✅ All syntax errors will be resolved
  • ✅ Sourcemaps will have clean single references

Why Delete .ts Instead of .js?

The .js files are:

  1. ✅ Actually imported throughout codebase
  2. ✅ Actually used at runtime
  3. ✅ The real source files

The .ts files are:

  1. ❌ Never imported (dead code)
  2. ❌ Only confusing SWC during compilation
  3. ❌ Incomplete migration artifacts

Codebase Architecture

This is a HYBRID JavaScript/TypeScript codebase:

# Real TypeScript files (actually used):
src/cli/commands/help.ts        ← Imported and used
src/cli/commands/help-new.ts    ← Imported and used
src/swarm/**/*.ts               ← Many real TS files

# Dead TypeScript duplicates (should remove):
src/cli/help-formatter.ts       ← Never imported
src/cli/simple-cli.ts           ← Never imported
# ... 7 more

Even TypeScript files import from .js:

// In src/cli/commands/help.ts:
import { HelpFormatter } from '../help-formatter.js'; // ← .js, not .ts!

Prevention Recommendations

1. Add Pre-Commit Hook

#!/bin/bash
# Check for duplicate .js/.ts files
duplicates=$(find src -type f \( -name "*.js" -o -name "*.ts" \) | 
  sed 's/\.[jt]s$//' | sort | uniq -d)

if [ -n "$duplicates" ]; then
  echo "❌ Error: Found duplicate .js/.ts files:"
  echo "$duplicates"
  exit 1
fi

2. ESLint Rule

Add to .eslintrc:

{
  "rules": {
    "import/extensions": ["error", "always", {
      "js": "always",
      "ts": "never"
    }]
  }
}

3. Build Validation

Add to CI/CD:

# Detect duplicate .js/.ts files
duplicates=$(find src -type f \( -name "*.js" -o -name "*.ts" \) | 
  sed 's/\.[jt]s$//' | sort | uniq -d)

if [ -n "$duplicates" ]; then
  echo "❌ Error: Duplicate .js/.ts files found"
  exit 1
fi

4. Documentation

Add to CONTRIBUTING.md:

## TypeScript Migration Guidelines

When converting files to TypeScript:
1. Create `.ts` version with types
2. Update ALL imports to reference `.ts`
3. Delete original `.js` file
4. Test build to ensure no duplicates
5. Verify imports work correctly

**DO NOT** commit both `.js` and `.ts` versions of the same file.

Timeline

  • July 17, 2025: Duplicate files introduced during "TypeScript migration"
  • 3+ months: Issue went undetected (only affected batch builds with sourcemaps)
  • October 21, 2025: Discovered when MCP server failed to start
  • October 23, 2025: Root cause identified (9 duplicate files)

Testing Verification

Current State (with duplicates):

$ node dist-cjs/src/cli/simple-cli.js mcp start
SyntaxError: Invalid or unexpected token

Expected After Fix:

$ node dist-cjs/src/cli/simple-cli.js mcp start
✅ Starting Claude Flow MCP server in stdio mode...
[ReasoningBank] Initialization complete

Related Information

  • Relates to previous TypeScript migration efforts (commit 7a56064)
  • May affect other repositories with similar hybrid JS/TS patterns
  • SWC version: 0.7.8 / 1.13.19 (behavior confirmed with these versions)

Action Items

  • Remove all 9 duplicate .ts files listed above
  • Verify MCP server starts correctly after removal
  • Add pre-commit hook to prevent recurrence
  • Add ESLint rule for import extensions
  • Add CI/CD validation for duplicate detection
  • Update CONTRIBUTING.md with migration guidelines
  • Audit codebase for any other duplicate patterns
  • Consider completing TypeScript migration properly (or standardize on JavaScript)

Lessons Learned

  1. Complete migrations: Don't leave partial conversions
  2. Update imports: When renaming/converting files, update ALL references
  3. Test batch builds: Some issues only appear during full rebuilds
  4. Catch duplicates early: Linting and pre-commit hooks are essential
  5. Hidden bugs: Corruption in compiled output may not show in source
  6. 3-month latency: Issue existed but only caused visible failure when MCP server tried to execute corrupted code

Affected Versions: v2.0.0-alpha.61 through v2.7.0-alpha.14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions