cloudflare / cloudflare/opaque-ts
@cloudflare/opaque-ts crashes under Cloudflare Workers / vitest-pool-workers during module load via @cloudflare/voprf-ts sjcl interop
- Dominant language
- TypeScript
- Stars
- 111
- Forks
- 14
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
`@cloudflare/opaque-ts` fails to load in the Cloudflare Workers Vitest runtime.
If a Worker entrypoint imports code that eventually imports `@cloudflare/opaque-ts`, tests fail before any tests execute.
The failure happens during module evaluation, not when actually calling OPAQUE APIs.
## Environment
- `@cloudflare/opaque-ts`: `0.7.5`
- `@cloudflare/vitest-pool-workers`: `0.14.7`
- `vitest`: `4.1.4`
- `wrangler`: `4.83.0`
- Node: `v24.1.0`
- OS: macOS
## Error
```txt
TypeError: Cannot set property default of [object Module] which has only a getter
❯ .../@cloudflare/voprf-ts/lib/src/sjcl/index.js:3141:20
3139| };
3140| if (typeof module !== 'undefined' && module.exports) {
3141| module.exports = sjcl;
```
This appears to come from the @cloudflare/opaque-ts -> @cloudflare/voprf-ts -> sjcl path.
## Expected behavior
A Worker module graph that imports @cloudflare/opaque-ts should be loadable in the Cloudflare Workers runtime / test runtime.
## Actual behavior
The runtime crashes during module load and no tests run.
## Repro shape
I have a Worker entrypoint that imports an auth service graph. That graph includes an OpaqueService which imports @cloudflare/opaque-ts.
- If my Vitest Worker config points main at the real Worker entrypoint, the suites fail immediately with the error above.
- If I instead point main at a minimal test-only Worker that avoids importing the auth graph / @cloudflare/opaque-ts, the same tests pass.
So the issue is specifically triggered by loading @cloudflare/opaque-ts in the Workers runtime.
## Additional notes
I also tried forcing the dependency chain through Vitest/Vite transforms:
- server.deps.inline
- ssr.noExternal
for:
- @cloudflare/opaque-ts
- @cloudflare/voprf-ts
- sjcl
That did not change the failure.
It looks like the problem is the sjcl interop inside @cloudflare/voprf-ts, which @cloudflare/opaque-ts pulls in.
Contributor guide
Assessment
This issue has not been assessed yet.