Workers SDK Issue Reports

← Back to Dashboard

#5308 Malformed _routes.json does not throw error but fails silently

Recommendation:KEEP OPEN
Difficulty:easy
Reasoning:

Bug confirmed in current codebase. JSON.parse SyntaxError is silently swallowed in deploy.ts catch block that only re-throws FatalError instances.

Suggested Action:

Implement fix to handle SyntaxError from JSON.parse and throw user-friendly FatalError with JSON syntax details.

Analysis Report

Issue Review: cloudflare/workers-sdk#5308

Summary

Malformed _routes.json files with invalid JSON syntax (e.g., trailing commas) silently fail during Pages deployment instead of throwing an error.

Review Findings

Step 1 - Issue Details

Field Value
Created 2024-03-20
Last Updated 2025-10-30
Reporter Version 3.35.0
Current Version 4.60.0
Component Pages, Wrangler
Labels bug
Comments 1 (maintainer acknowledgment)

Issue Description:
When deploying to Pages with a _routes.json file containing invalid JSON (specifically a trailing comma), the deployment succeeds without any error, but the _routes.json file is not uploaded. The user expects a clear error message about the malformed JSON.

The example provided shows a common JSON syntax error:

{
   "version": 1,
   "include": ["/*"],
   "exclude": [
      "/assets/*",   // <-- trailing comma is invalid JSON
    ]
}

Step 2 - Issue Validity

Issue content is valid and complete with:

  • Clear reproduction steps
  • Specific example of the malformed JSON
  • Clear expected behavior (should throw an error)
  • Clear observed behavior (silently fails)

Step 3 - Label Analysis

  • Has bug label - appropriate for this issue
  • No awaiting reporter response, duplicate, or resolution labels
  • Single comment from maintainer @penalosa (Aug 2024) suggesting it "might have been partially addressed" by @CarmenPopoviciu's work, but no confirmation

Step 4 - Related Fixes

No PRs found that directly fix this issue.

Searched for:

  • PRs mentioning issue #5308 - none found
  • PRs related to _routes.json validation - none addressing JSON parse errors
  • PRs by @CarmenPopoviciu related to routes - no relevant fixes found

Related PR #5166 (feat(wrangler): Add config validation for Pages) merged 2024-03-18 adds wrangler.toml validation but does NOT address _routes.json JSON syntax validation.

Step 5 - Changelog Check

No changelog entries found referencing:

  • Issue #5308
  • JSON parse error handling for _routes.json
  • Malformed routes.json validation

Step 6 - Version Gap

  • Reported version: 3.35.0
  • Current version: 4.60.0
  • Gap: ~125 minor versions (significant)

However, version gap is not conclusive here since no fix has been identified.

Step 7 - Code Analysis (in lieu of reproduction)

Examined the current source code at packages/wrangler/src/api/pages/deploy.ts:

if (_routesCustom) {
  // user provided a custom _routes.json file
  try {
    const routesCustomJSON = JSON.parse(_routesCustom);
    validateRoutes(routesCustomJSON, join(directory, "_routes.json"));

    formData.append(
      "_routes.json",
      new File([_routesCustom], "_routes.json")
    );
    logger.log(`✨ Uploading _routes.json`);
  } catch (err) {
    if (err instanceof FatalError) {
      throw err;
    }
    // BUG: JSON.parse SyntaxError is silently swallowed here!
  }
}

Root Cause Confirmed:
The catch block only re-throws FatalError instances. When JSON.parse() fails due to malformed JSON (e.g., trailing comma), it throws a native SyntaxError, which is NOT a FatalError. This error is silently caught and ignored, causing the deployment to proceed without uploading the _routes.json file.

The validateRoutes() function in routes-validation.ts properly validates the JSON structure AFTER parsing, but the issue occurs BEFORE this validation can run.

Recommendation

Status: KEEP OPEN

Reasoning

The bug is still present in the current codebase. The code analysis clearly shows that:

  1. JSON.parse() errors are caught but not handled properly
  2. Only FatalError instances are re-thrown
  3. SyntaxError from malformed JSON is silently ignored
  4. The deployment proceeds without the _routes.json file

The maintainer's August 2024 comment suggesting it "might have been partially addressed" appears to be incorrect - no related fixes have been merged.

Suggested Action

This is a valid, confirmed bug that needs a fix. The fix is straightforward:

Option 1 (Recommended): Re-throw JSON.parse errors with a user-friendly message

try {
  const routesCustomJSON = JSON.parse(_routesCustom);
  // ... validation
} catch (err) {
  if (err instanceof SyntaxError) {
    throw new FatalError(
      `Invalid JSON syntax in _routes.json at: ${join(directory, "_routes.json")}\n` +
      `Error: ${err.message}`,
      1
    );
  }
  if (err instanceof FatalError) {
    throw err;
  }
  throw err; // Re-throw any other unexpected errors
}

Option 2: Add a warning but continue deployment (less recommended)

The fix should be applied in both locations where _routesCustom is parsed in deploy.ts (Advanced Mode and Functions sections).

Suggested Comment

Thanks for reporting this issue. After investigating, I can confirm this bug is still present in the current codebase.

Root Cause: When _routes.json contains invalid JSON syntax (like trailing commas), the JSON.parse() call throws a SyntaxError, which is silently caught and ignored. This causes the deployment to proceed without uploading the routes file.

Affected code: packages/wrangler/src/api/pages/deploy.ts - the catch blocks only re-throw FatalError instances, not native JavaScript errors like SyntaxError.

This should be a straightforward fix - we need to handle SyntaxError from JSON.parse() and throw a user-friendly FatalError with details about the JSON syntax issue.


Solution Recommendation

Root Cause Analysis

File: packages/wrangler/src/api/pages/deploy.ts
Lines: 376-392 and 411-426

The bug is in identical catch blocks that handle custom _routes.json files:

if (_routesCustom) {
    try {
        const routesCustomJSON = JSON.parse(_routesCustom);  // SyntaxError thrown here
        validateRoutes(routesCustomJSON, join(directory, "_routes.json"));
        // ...
    } catch (err) {
        if (err instanceof FatalError) {  // BUG: SyntaxError is NOT a FatalError
            throw err;
        }
        // SyntaxError is silently swallowed here!
    }
}

Correct behavior exists in dev.ts at lines 819-827:

} catch (err) {
    if (err instanceof FatalError) {
        throw err;
    } else {
        throw new FatalError(
            `Could not validate _routes.json at ${directory}: ${err}`,
            1
        );
    }
}

Proposed Solution

Modify the catch blocks in deploy.ts to match the behavior in dev.ts:

} catch (err) {
    if (err instanceof FatalError) {
        throw err;
    } else if (err instanceof SyntaxError) {
        throw new FatalError(
            `Malformed JSON in _routes.json at ${join(directory, "_routes.json")}: ${err.message}`,
            1
        );
    } else {
        throw new FatalError(
            `Could not process _routes.json at ${join(directory, "_routes.json")}: ${err}`,
            1
        );
    }
}

Apply this fix at both locations (lines 387-391 and 422-426).

Implementation Difficulty: Easy

Factor Assessment
Lines of code ~10-15 lines (2 catch blocks)
Risk Low - only affects error handling path
Testing Easy - existing test patterns available
Scope Single file (deploy.ts)
Pattern exists Yes - correct implementation in dev.ts

Files to Modify

  1. packages/wrangler/src/api/pages/deploy.ts - Fix catch blocks at lines 387-391 and 422-426
  2. packages/wrangler/src/__tests__/pages/deploy.test.ts - Add tests for malformed JSON

Testing Recommendations

  1. Test trailing comma in _routes.json → expect clear error message
  2. Test completely invalid JSON → expect clear error message
  3. Test empty _routes.json file → expect clear error message
  4. Test valid JSON with missing required fields → existing behavior (FatalError)
  5. Verify error message includes file path and JSON syntax details

Notes & Feedback (0)

No notes yet.

Add Note