#5308 Malformed _routes.json does not throw error but fails silently
Bug confirmed in current codebase. JSON.parse SyntaxError is silently swallowed in deploy.ts catch block that only re-throws FatalError instances.
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
buglabel - 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:
JSON.parse()errors are caught but not handled properly- Only
FatalErrorinstances are re-thrown SyntaxErrorfrom malformed JSON is silently ignored- The deployment proceeds without the
_routes.jsonfile
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.jsoncontains invalid JSON syntax (like trailing commas), theJSON.parse()call throws aSyntaxError, 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-throwFatalErrorinstances, not native JavaScript errors likeSyntaxError.This should be a straightforward fix - we need to handle
SyntaxErrorfromJSON.parse()and throw a user-friendlyFatalErrorwith 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
packages/wrangler/src/api/pages/deploy.ts- Fix catch blocks at lines 387-391 and 422-426packages/wrangler/src/__tests__/pages/deploy.test.ts- Add tests for malformed JSON
Testing Recommendations
- Test trailing comma in
_routes.json→ expect clear error message - Test completely invalid JSON → expect clear error message
- Test empty
_routes.jsonfile → expect clear error message - Test valid JSON with missing required fields → existing behavior (FatalError)
- Verify error message includes file path and JSON syntax details
Notes & Feedback (0)
No notes yet.