Skip to content

Conversation

@NathanFlurry
Copy link
Member

@NathanFlurry NathanFlurry commented Nov 6, 2025

RequestInit: duplex option is required when sending a body.

@vercel
Copy link

vercel bot commented Nov 6, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
rivetkit-serverless Ready Ready Preview Comment Nov 6, 2025 5:37am
3 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
rivet-cloud Ignored Ignored Nov 6, 2025 5:37am
rivet-inspector Ignored Ignored Preview Nov 6, 2025 5:37am
rivet-site Ignored Ignored Preview Nov 6, 2025 5:37am

Copy link
Member Author

NathanFlurry commented Nov 6, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link

claude bot commented Nov 6, 2025

Code Review for PR #3388

Summary

This PR adds the duplex: "half" property to a RequestInit object in the Next.js development request handler. The change addresses a runtime error about missing the duplex option when sending a body.

✅ Positive Aspects

  1. Correct Fix: The duplex property is indeed required when creating a Request with a streaming body according to the Fetch API specification. This prevents the runtime error mentioned in the PR description.

  2. Appropriate Scope: The fix is minimal and surgical - only affecting the development-specific request handler path where the file watcher is enabled.

  3. Type Safety: The cast to as RequestInit is necessary since TypeScript's built-in types may not include the duplex property yet (it's a relatively newer addition to the spec).

  4. Good Comment: The inline comment "Required for streaming body" explains why this property is needed.

🔍 Observations & Suggestions

1. Consistency with Production Path

The production path (lines 59-61) creates a Request differently:

const newReq = new Request(newUrl, request);

While the development path explicitly copies all properties. Consider whether the production path might need the same fix if it encounters requests with bodies. The simplified constructor new Request(newUrl, request) should theoretically copy the duplex setting automatically, but this should be verified.

Recommendation: Test or document whether the production path handles POST/PUT/PATCH requests with bodies correctly, or if it needs the same explicit duplex configuration.

2. TypeScript Type Cast

The as RequestInit cast bypasses TypeScript's type checking. While necessary here, it could hide future type issues.

Recommendation: Consider adding a comment explaining why the cast is necessary (TypeScript types may lag behind the spec) to help future maintainers.

3. Missing Test Coverage

No test files were found for this package. The change affects request handling with bodies, which should ideally have test coverage.

Recommendation: Consider adding integration tests that verify:

  • POST/PUT/PATCH requests with bodies work correctly in development mode
  • The file watcher correctly handles requests with streaming bodies
  • The duplex setting doesn't cause issues with different request types

4. Error Handling

The current implementation doesn't validate whether request.body is compatible with the duplex setting.

Recommendation: Consider defensive checks, though the current implementation is likely fine for the intended use case.

🎯 Code Quality Assessment

  • Best Practices: ✅ Follows minimal change principle
  • Security: ✅ No security concerns identified
  • Performance: ✅ No performance impact (only affects development mode)
  • Maintainability: ✅ Clear and well-commented

Final Verdict

LGTM with minor suggestions. This is a solid fix for a real runtime issue. The main improvement would be ensuring test coverage for request handling with bodies, and potentially verifying the production code path handles this correctly as well.

The change is safe to merge as-is, with the suggestions being opportunities for future enhancement rather than blockers.

@claude
Copy link

claude bot commented Nov 6, 2025

PR Review: Fix missing duplex in Next.js development

Summary

This PR fixes a runtime error in Next.js development mode by adding the required duplex: "half" option when creating a Request with a streaming body.

Code Quality ✅

Positive aspects:

  • The fix is minimal and surgical - only adds what's needed
  • Uses as RequestInit type assertion, consistent with similar patterns in the codebase
  • Comment clearly explains why the option is needed
  • Follows existing patterns used throughout the codebase (found in gateway.ts:121, router.ts:633, actor/router.ts:265, etc.)

Consistency: This pattern is already used in 7+ other locations in the rivetkit-typescript codebase, making this change consistent with established practices.

Potential Issues ⚠️

1. Missing conditional check:
The fix adds duplex: "half" unconditionally, but I noticed in client/raw-utils.ts:56-58 there's a conditional pattern:

if (mergedInit.body) {
    (mergedInit as any).duplex = "half";
}

Since request.body is being passed (line 112), it could potentially be null or undefined for GET/HEAD requests. The fetch spec only requires duplex when a body is present. Consider adding:

...(request.body ? { duplex: "half" } : {}),

However, if all requests going through handleRequestWithFileWatcher are guaranteed to have bodies, the current implementation is fine.

Security Considerations ✅

No security concerns. The duplex: "half" option is a standard fetch API configuration for handling streaming request bodies.

Performance Considerations ✅

No performance impact. This is a configuration option that enables proper streaming behavior - it doesn't add computational overhead.

Test Coverage ⚠️

Observation: No test files exist in rivetkit-typescript/packages/next-js/.

Recommendation: While this is a small fix, consider adding integration tests for:

  • Requests with bodies in development mode
  • Requests without bodies in development mode
  • Verify the file watcher functionality works correctly

Questions

  1. Are all requests passing through handleRequestWithFileWatcher guaranteed to have bodies, or could GET/HEAD/OPTIONS requests with no body reach this code path?
  2. Has this been tested with various HTTP methods (GET, POST, PUT, etc.) in Next.js development mode?

Final Verdict

Approve with minor suggestion

The fix correctly addresses the reported error and follows existing codebase patterns. The only consideration is whether the duplex option should be conditional on request.body being present, similar to raw-utils.ts.


Review performed by Claude Code

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 6, 2025

More templates

@rivetkit/actor

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/actor@3388

@rivetkit/cloudflare-workers

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/cloudflare-workers@3388

@rivetkit/core

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/core@3388

@rivetkit/db

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/db@3388

@rivetkit/framework-base

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/framework-base@3388

@rivetkit/next-js

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/next-js@3388

@rivetkit/react

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/react@3388

rivetkit

pnpm add https://pkg.pr.new/rivet-dev/rivet/rivetkit@3388

@rivetkit/sql-loader

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/sql-loader@3388

@rivetkit/engine-runner

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner@3388

@rivetkit/engine-runner-protocol

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner-protocol@3388

commit: c4582a0

@claude
Copy link

claude bot commented Nov 6, 2025

Code Review

Summary

This PR fixes a RequestInit: duplex option is required when sending a body error in Next.js development mode by adding the duplex: "half" property to the Request constructor.

Positive Observations

Correct Fix: The change addresses a legitimate issue with the Fetch API specification. When creating a Request with a streaming body, the duplex property is required.

Consistent with Codebase: I found 7+ other instances throughout the codebase where duplex: "half" is already being used in similar contexts:

  • rivetkit/src/client/raw-utils.ts:58 - conditionally adds duplex when body is present
  • rivetkit/src/manager/gateway.ts:121, 334
  • rivetkit/src/manager/router.ts:633
  • rivetkit/src/actor/router.ts:265
  • Multiple test files

Proper Type Casting: Using as RequestInit is appropriate here since TypeScript's built-in types may not include the duplex property (it's a newer addition to the spec).

Good Comment: The inline comment explains why this property is needed.

Potential Issues & Suggestions

⚠️ Consider Conditional Application: Looking at raw-utils.ts:56-58, there's a pattern of conditionally adding duplex only when a body is present:

if (mergedInit.body) {
    (mergedInit as any).duplex = "half";
}

In handleRequestWithFileWatcher, you're always setting duplex: "half" even though request.body could potentially be null for GET/HEAD requests. While this shouldn't cause issues (it's technically valid), it would be more precise to conditionally set it:

const newReq = new Request(newUrl, {
    method: request.method,
    headers: request.headers,
    body: request.body,
    credentials: request.credentials,
    cache: request.cache,
    redirect: request.redirect,
    referrer: request.referrer,
    integrity: request.integrity,
    signal: mergedController.signal,
    ...(request.body && { duplex: "half" }),
} as RequestInit);

However, this is a minor point and the current implementation is acceptable.

⚠️ Test Coverage: There are no test files for the next-js package. Consider adding integration tests that verify:

  1. Requests with bodies work correctly in development mode
  2. The file watcher functionality operates as expected
  3. Stream handling works properly

Security & Performance

No Security Concerns: The change is purely fixing a spec compliance issue.

No Performance Impact: Adding a property to the RequestInit object has negligible performance impact.

Verdict

LGTM 👍 This is a valid bug fix that aligns with the Fetch API specification and follows patterns already established in the codebase. The only minor suggestion is to consider conditional application of the duplex property (matching the pattern in raw-utils.ts), but this is not a blocker.


Review performed by Claude Code - #3388

@NathanFlurry NathanFlurry force-pushed the 11-05-fix_rivetkit_fix_missing_duplex_in_nextjs_in_development branch from 64aafa4 to b515fae Compare November 6, 2025 02:16
@NathanFlurry NathanFlurry force-pushed the 11-05-chore_runner_add_safeguard_against_duplicate_sockets branch from 91efc39 to b80bfa4 Compare November 6, 2025 02:16
@claude
Copy link

claude bot commented Nov 6, 2025

PR Review: Fix missing duplex in Next.js development

Summary

This PR adds the duplex: "half" option to the RequestInit when creating a new Request object in development mode. This fixes the error: "RequestInit: duplex option is required when sending a body."

Code Quality ✅

Positive:

  • The fix directly addresses the error mentioned in the PR description
  • The change is minimal and focused
  • Added a helpful comment explaining why the property is needed
  • Uses type assertion as RequestInit to handle TypeScript typing issues with the duplex property

Observations:

  • The duplex property is required by the Fetch API spec when a Request has a body that might be read more than once or streamed
  • The fix only applies to the development path (line 58-65), which makes sense given the PR title

Potential Issues 🔍

Minor considerations:

  1. Production path missing same fix: The non-development path (lines 58-61) also creates a Request with a body:

    const newReq = new Request(newUrl, request);

    This might encounter the same error in production if the request has a body. Consider whether this needs the same fix.

  2. Type assertion: The as RequestInit cast is necessary because TypeScript's built-in types don't include the duplex property yet (it's a newer addition to the spec). This is acceptable but worth noting for future TypeScript version updates.

Testing Considerations 🧪

  • No automated tests exist for this package currently
  • The fix addresses a runtime error that would occur during development
  • Manual testing should verify:
    • POST/PUT/PATCH requests with bodies work in development mode
    • File watching still functions correctly
    • No regression in production builds

Performance ✅

  • No performance impact
  • The duplex: "half" value indicates the body can be read once (half-duplex), which is standard for most HTTP requests

Security ✅

  • No security concerns
  • The change doesn't affect authentication, authorization, or data handling

Recommendations

  1. Consider applying to production path too: Evaluate whether the production request creation (line 60) needs the same fix:

    const newReq = new Request(newUrl, {
        ...request,
        duplex: "half",
    } as RequestInit);
  2. Add a test: While not blocking, consider adding a basic integration test that verifies requests with bodies work correctly in development mode.

Verdict ✅

LGTM - This is a solid fix for the development environment issue. The only consideration is whether the production path needs the same treatment, but that can be addressed in a follow-up if needed.


Review generated with Claude Code

@claude
Copy link

claude bot commented Nov 6, 2025

Pull Request Review

Summary

This PR fixes a duplex option is required when sending a body error that occurs in Next.js development mode when creating a new Request with a body.

✅ Positive Findings

1. Correct Fix
The addition of duplex: "half" is the correct solution for the error. When creating a new Request with a body in the Fetch API, the duplex property is required to indicate the streaming direction.

2. Consistent with Codebase Patterns
This fix follows existing patterns in the codebase:

  • packages/rivetkit/src/manager/gateway.ts:121 - Uses the same duplex: "half" with as RequestInit cast
  • packages/rivetkit/src/client/raw-utils.ts:58 - Conditionally adds duplex when body is present
  • Multiple other files use this exact pattern (router.ts, actor-http-client.ts, etc.)

3. Appropriate TypeScript Cast
The as RequestInit cast is necessary because TypeScript's built-in types don't yet include the duplex property, which is a relatively newer addition to the Fetch standard.

4. Good Code Comment
The inline comment // Required for streaming body clearly explains why this property is needed.

🤔 Observations & Suggestions

1. Inconsistency with Production Code Path
The production code path (line 60) creates a Request differently:

const newReq = new Request(newUrl, request);

This uses the Request copy constructor, which should automatically handle the duplex property. However, the development path manually spreads all properties and rebuilds the Request, which is why the duplex property needs to be explicitly set.

Question: Could the development path also use the Request copy constructor approach and only override the signal? For example:

const newReq = new Request(newUrl, {
  ...request,
  signal: mergedController.signal,
});

This might avoid the need for manual duplex handling, though I understand there may be specific reasons for the current approach.

2. Conditional Duplex (Minor)
In raw-utils.ts:57-58, duplex is only added when a body is present:

if (mergedInit.body) {
  (mergedInit as any).duplex = "half";
}

While the current fix always adds duplex, this appears safe since having it when there's no body shouldn't cause issues. However, for consistency with other parts of the codebase, you could consider:

// Required for streaming body
...(request.body && { duplex: "half" }),

That said, this is a minor point and the current approach is perfectly valid.

🧪 Test Coverage

Observation: No test files exist for this package (rivetkit-typescript/packages/next-js/).

Recommendation: While this fix is straightforward, consider adding integration tests that:

  • Verify requests with bodies work in development mode
  • Test the file watcher functionality
  • Ensure both GET (no body) and POST (with body) requests work correctly

This would prevent regressions and make the package more robust.

🔒 Security & Performance

Security: ✅ No security concerns. The change only affects request creation mechanics.

Performance: ✅ No performance impact. Adding a property to an options object has negligible overhead.

Final Verdict

✅ LGTM (Looks Good To Me)

This is a solid bug fix that:

  • Correctly addresses the reported error
  • Follows established patterns in the codebase
  • Uses appropriate TypeScript handling
  • Has clear documentation via comment

The suggestions above are minor improvements for consideration, not blockers. The PR is ready to merge as-is.


Recommendation: Approve and merge.

@NathanFlurry NathanFlurry force-pushed the 11-05-fix_rivetkit_fix_missing_duplex_in_nextjs_in_development branch from b515fae to c4582a0 Compare November 6, 2025 05:36
@NathanFlurry NathanFlurry force-pushed the 11-05-chore_runner_add_safeguard_against_duplicate_sockets branch from b80bfa4 to 7091bb6 Compare November 6, 2025 05:36
@claude
Copy link

claude bot commented Nov 6, 2025

Code Review - PR #3388

Summary

This PR fixes a runtime error in Next.js development mode by adding the required duplex: "half" option when creating a Request with a body. The fix is correct and consistent with similar patterns elsewhere in the codebase.

✅ Positive Findings

1. Correct Fix
The error message indicates that the Fetch API requires the duplex option when a Request has a body. This is a known requirement for streaming request bodies. The fix correctly adds duplex: "half".

2. Consistent with Codebase Patterns
I found 6+ other locations in the rivetkit-typescript codebase that use the same pattern:

  • rivetkit-typescript/packages/rivetkit/src/manager/gateway.ts:121
  • rivetkit-typescript/packages/rivetkit/src/manager/router.ts:633
  • rivetkit-typescript/packages/rivetkit/src/actor/router.ts:265
  • rivetkit-typescript/packages/rivetkit/src/client/raw-utils.ts:58

All these files cast to as RequestInit when adding duplex: "half", which is exactly what this PR does.

3. Appropriate Use of Type Assertion
The as RequestInit cast is necessary because TypeScript's type definitions may not include the duplex property (it's a relatively new addition to the Fetch spec). This is the standard workaround used throughout the codebase.

4. Good Comment
The inline comment "Required for streaming body" clearly explains why this property is needed.

🔍 Observations

1. Scope is Correct
The fix only applies to the development path (handleRequestWithFileWatcher), which makes sense since:

  • This is where the error was occurring (line 58-64 shows dev mode uses this function)
  • The production path (line 60) creates a simpler Request without these complications
  • The dev-only file watcher logic justifies the more complex Request construction

2. Request Body Handling
The code copies body: request.body from the original request. This should work correctly since:

  • Request bodies can be transferred between Request objects
  • The duplex: "half" option indicates half-duplex streaming (read OR write, not both)
  • This is appropriate for proxying a request body

🤔 Minor Considerations

1. Conditional Application
Looking at raw-utils.ts:57-59, there's a pattern where duplex is only added conditionally if a body exists:

if (mergedInit.body) {
    (mergedInit as any).duplex = "half";
}

However, in this case, always adding duplex: "half" is fine because:

  • The error message indicates it's required when sending a body
  • If there's no body, the duplex option is harmless (it's ignored)
  • All other files in the codebase add it unconditionally when copying request bodies
  • The overhead is negligible

2. Test Coverage
No test files exist for next-js/src/mod.ts. While this fix is straightforward, integration tests for the Next.js handler would be valuable for catching similar issues in the future. (This is not blocking for this PR, just a general observation.)

✅ Final Verdict

Approve - This is a clean, correct fix that:

  • ✅ Solves the reported error
  • ✅ Follows existing codebase patterns
  • ✅ Has appropriate type handling
  • ✅ Includes a helpful comment
  • ✅ Is scoped to the right location (dev mode only)
  • ✅ Has no security concerns
  • ✅ Has no performance impact

Recommendation

Merge - No changes needed.

@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 6, 2025

Merge activity

  • Nov 6, 5:47 AM UTC: NathanFlurry added this pull request to the Graphite merge queue.
  • Nov 6, 5:48 AM UTC: CI is running for this pull request on a draft pull request (#3395) due to your merge queue CI optimization settings.
  • Nov 6, 5:50 AM UTC: Merged by the Graphite merge queue via draft PR: #3395.

graphite-app bot pushed a commit that referenced this pull request Nov 6, 2025
```
RequestInit: duplex option is required when sending a body.
```
@graphite-app graphite-app bot closed this Nov 6, 2025
@graphite-app graphite-app bot deleted the 11-05-fix_rivetkit_fix_missing_duplex_in_nextjs_in_development branch November 6, 2025 05:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants