Fixing Zod V4 Compatibility In @trigger.dev/core
Welcome, fellow developers! Today, we're diving deep into a tricky, yet common, challenge many of us face when integrating powerful tools in our projects: dependency compatibility issues. Specifically, we'll be tackling a significant hiccup involving Zod v4 and the otherwise fantastic @trigger.dev/core library. If you've been scratching your head over mysterious "Connection error" messages or TypeErrors related to Zod internals, even when your project explicitly allows Zod v4, then you're in the right place. This article aims to unravel the mystery, explain the root cause, and provide clear solutions and workarounds, ensuring your Trigger.dev integrations run smoothly with modern Zod versions. We'll explore why this Zod v4 compatibility problem occurs, how it manifests, and what steps you can take to resolve it, making your development experience much more pleasant and productive.
Unpacking the Mysterious TypeError and Misleading TriggerApiError
Many developers, ourselves included, have encountered a perplexing issue where @trigger.dev/core@4.3.0 seems to clash with Zod v4 in their projects. The problem often starts with a cryptic runtime error: TypeError: undefined is not an object (evaluating 't.valueType._zod'). This error, while seemingly low-level, points to a deeper Zod version incompatibility. What makes this particularly frustrating is that the actual error message you often see at the top level is a misleading TriggerApiError: Connection error.. Imagine trying to debug a network issue for hours, only to discover the true culprit is a dependency conflict deep within your application's validation logic! This TriggerApiError can send you down a rabbit hole of checking network configurations, API keys, and firewall settings, when the real problem lies much closer to home.
This misleading error message is a major pain point because it obscures the true nature of the problem. It doesn't indicate a network failure at all; rather, it suggests an internal SDK validation or serialization process is failing before any HTTP request even gets a chance to be made. The stack trace clearly shows the TypeError originating from an internal module within the SDK's bundled code, specifically trying to access t.valueType._zod. For those familiar with Zod's internal structure, the _zod property was an internal detail of Zod v3 schemas. It was used by certain libraries to inspect or manipulate schema types. However, with the significant architectural changes introduced in Zod v4, this internal property was removed, refactored, or simply no longer exists in the same way. When an older dependency, like a specific version of zod-validation-error, attempts to access this non-existent _zod property within a project using Zod v4, it inevitably results in an undefined value, leading directly to the TypeError. This creates a critical breakdown in the SDK's ability to validate or serialize data, effectively halting any operations that rely on this underlying Zod validation mechanism. The frustration is compounded by the fact that @trigger.dev/core's own peer dependency declaration for Zod explicitly allows "zod": "^3.0.0 || ^4.0.0", which implies that Zod v4 should work out of the box. This discrepancy between the stated compatibility and the actual runtime behavior is precisely what makes this Zod v4 compatibility issue so challenging to diagnose without deep introspection into the dependency tree. Understanding that the Connection error is a red herring and the TypeError is the true signal of a Zod version mismatch is the first crucial step in resolving this puzzle.
The Root Cause: A zod-validation-error Version Mismatch
At the heart of this Zod v4 compatibility issue lies a specific dependency within @trigger.dev/core@4.3.0: zod-validation-error. While @trigger.dev/core itself declares a peer dependency that allows for both Zod v3 and Zod v4, its direct dependency on zod-validation-error@^1.5.0 is the actual culprit. This particular version of zod-validation-error was developed with Zod v3 in mind and, crucially, relies on accessing internal properties of Zod schemas, specifically t.valueType._zod. As we discussed, this _zod property, an internal mechanism of Zod v3, simply does not exist in Zod v4. When your project installs Zod v4 (as allowed by the peer dependency), zod-validation-error@^1.5.0 tries to find this property on Zod v4 schemas, finds undefined, and throws the TypeError we've been seeing.
Let's break down the dependency declaration from @trigger.dev/core@4.3.0's package.json:
{
"dependencies": {
"zod": "3.25.76",
"zod-validation-error": "^1.5.0"
}
}
Notice the zod direct dependency here is fixed at 3.25.76. While this seems to guarantee Zod v3, when your root project depends on zod@^4.2.1 (or any Zod v4 version), package managers like npm, yarn, or pnpm will try to hoist and deduplicate dependencies. If @trigger.dev/core's direct zod dependency is a specific patch version and your project's Zod dependency is a major version range that allows Zod v4, the package manager might end up installing two versions of Zod, or, more commonly in a hoisted scenario, provide the project's Zod v4 instance to zod-validation-error if it's the more dominant or compatible version found in the hoisted node_modules. Regardless of the exact hoisting behavior, the fundamental problem is that zod-validation-error@^1.5.0 is not compatible with Zod v4's API changes. It's expecting the older Zod v3 internals, and when it doesn't find them, everything grinds to a halt. This creates a challenging situation because developers naturally expect that if an SDK declares compatibility with a major version like Zod v4, it should just work. The zod-validation-error package underwent its own major version update (to v4) specifically to support Zod v4 and its new internal structure. Therefore, the core of the issue is that @trigger.dev/core is pulling in an outdated version of zod-validation-error that simply doesn't understand Zod v4's internal schema structure, leading to the crashes during internal validation. This highlights the intricate nature of dependency trees and why keeping all components up-to-date with their respective major version changes is crucial for avoiding these kinds of hidden compatibility snags that can be incredibly time-consuming to diagnose.
Reproducing the Issue: A Clear Path to Error
To truly grasp the scope of this Zod v4 compatibility issue, it's helpful to walk through a clear reproduction scenario. This isn't just theory; it's a real-world problem that can halt your development flow. The setup involves a common modern JavaScript environment, highlighting how seemingly correct dependency configurations can still lead to unexpected runtime errors. We've seen this issue consistently arise in specific setups, proving that while @trigger.dev/core claims Zod v4 compatibility, an underlying dependency prevents it.
Let's outline the environment and code that reliably triggers this error:
Environment Configuration:
- Your project is using
@trigger.dev/sdk@4.3.0. - Crucially, your project's
package.jsonspecifies a modern Zod v4 version, for example,"zod": "^4.2.1". - The
@trigger.dev/sdk's peer dependency for Zod explicitly states:"zod": "^3.0.0 || ^4.0.0". This is what makes the situation so confusing, as it suggests that Zod v4 should be fully supported.
The Problematic Code:
Consider any simple interaction with the @trigger.dev/sdk that involves authentication or data serialization, such as creating a public token:
import { auth as triggerAuth } from "@trigger.dev/sdk";
// All of these calls will predictably fail with the same Zod compatibility error:
await triggerAuth.createPublicToken();
await triggerAuth.createPublicToken({ scopes: { read: { runs: true } } });
await triggerAuth.createPublicToken({ expirationTime: "1h" });
The Unfortunate Result:
When you execute any of these createPublicToken calls, you won't get a successful response or even a network error in the traditional sense. Instead, the application will crash during the SDK's internal validation process, before any network request has a chance to be sent. The console will display a stack trace similar to this:
TriggerApiError: Connection error.
at iE (/app/apps/christmas-photo/.next/server/chunks/node_modules_5ba9120a._.js:6:6423)
at processTicksAndRejections (native)
TypeError: undefined is not an object (evaluating 't.valueType._zod')
at (.next/server/chunks/_70c3eef0._.js:19:6236)
Notice again the misleading TriggerApiError: Connection error. at the top. This message leads developers astray, making them believe there's an issue with network connectivity or the Trigger.dev API itself. However, the subsequent TypeError: undefined is not an object (evaluating 't.valueType._zod') is the real indicator of the problem. It clearly shows an attempt to access a Zod v3 internal property (_zod) on a Zod v4 schema, which no longer exists. This confirms that the failure happens internally within the SDK's dependency stack, not at the network layer. The issue occurs regardless of the specific parameters passed to createPublicToken, as the underlying validation logic is always invoked. This consistent reproduction across different inputs further solidifies the diagnosis: it's a fundamental Zod version incompatibility within @trigger.dev/core's sub-dependencies, not an issue with your specific usage or network setup. This detailed reproduction highlights the urgent need for a proper solution to ensure smooth integration with Zod v4 in Trigger.dev projects.
Solving the Zod V4 Compatibility Puzzle for Good
Thankfully, with a clear understanding of the Zod v4 compatibility issue stemming from zod-validation-error, we can propose a straightforward and effective solution. The key lies in updating the problematic sub-dependency to a version that properly supports Zod v4's architectural changes. This isn't about radically altering Trigger.dev's core, but rather ensuring its internal tools are up-to-date with the Zod ecosystem.
The Primary Proposed Solution:
The most direct and robust solution involves updating the zod-validation-error dependency within @trigger.dev/core to a version specifically designed for Zod v4 compatibility. The zod-validation-error package's own developers recognized this exact problem and released major updates to address it. Specifically, zod-validation-error@^4.0.1 (or any later 4.x.x version) is fully compatible with both Zod v3 and Zod v4 schemas. This version was created precisely to navigate the internal changes between Zod versions, eliminating the reliance on the deprecated _zod property.
Here’s how the package.json for @trigger.dev/core should look to resolve this issue:
{
"dependencies": {
"zod": "3.25.76", // Can be kept for backward compatibility if needed
"zod-validation-error": "^4.0.1" // <--- Crucial update for Zod v4 support
}
}
By making this change, zod-validation-error will correctly interpret schemas whether they originate from Zod v3 or Zod v4, thus preventing the TypeError: undefined is not an object (evaluating 't.valueType._zod') and the subsequent TriggerApiError: Connection error. messages. This is the most idiomatic fix, as it aligns the internal dependency with the broader ecosystem's evolution, ensuring Zod v4 compatibility without requiring developers to change their project's Zod version.
Alternative Solutions (Less Ideal, but Worth Considering):
While updating zod-validation-error is the cleanest fix, other approaches could be considered, though they come with their own trade-offs:
- Making
zod-validation-errora Peer Dependency: Ifzod-validation-errorwere made a peer dependency of@trigger.dev/core, it would place the responsibility on the end-user project to install a compatible version. This offers flexibility but shifts the burden to the developer, who might then face their own dependency resolution issues if they're not careful. It also means Trigger.dev would need to ensure that their internal code works with any compatiblezod-validation-errorversion, which can be complex. - Conditional Zod Logic: Theoretically,
@trigger.dev/corecould implement conditional logic to detect the installed Zod version (v3 or v4) and adapt its internal validation strategy accordingly. However, this adds significant complexity to the SDK itself and is generally less desirable than simply using azod-validation-errorversion that handles this logic internally.
For most practical purposes and to provide the best developer experience, the first solution—updating zod-validation-error to ^4.0.1 within @trigger.dev/core—is the clear winner. It directly addresses the Zod v4 compatibility problem at its source, requiring no changes from end-users and ensuring that the SDK functions reliably across modern Zod environments. Implementing this fix would significantly improve the stability and usability of @trigger.dev/core for projects leveraging Zod v4, making it a much smoother experience for everyone involved in building robust serverless workflows.
A Practical Workaround for Immediate Relief
While waiting for an official update to @trigger.dev/core to address the Zod v4 compatibility issue, we understand that you might need an immediate solution to keep your development moving forward. That's where a practical workaround comes in handy. This approach allows you to bypass the problematic SDK validation logic entirely, directly interacting with the Trigger.dev API to achieve your goals, such as creating public tokens.
Our workaround centers on leveraging the jose library, which is a JavaScript Object Signing and Encryption library that Trigger.dev itself uses internally for JWT (JSON Web Token) operations. By using jose directly, we can manually perform the steps that @trigger.dev/sdk attempts but fails due to the Zod v4 conflict. This strategy effectively side-steps the zod-validation-error dependency, confirming that the underlying Trigger.dev API is perfectly functional; the issue truly lies in the SDK's client-side validation.
Here’s a high-level overview of the workaround:
- Fetch JWT Claims: Instead of relying on
triggerAuth.createPublicToken(), we make a direct HTTP call to the Trigger.dev API endpoint/api/v1/auth/jwt/claims. This endpoint provides the necessary claims (data) that would typically be included in a JWT for authentication. You'll need to use a standardfetchcall or an HTTP client to retrieve this information. Ensure your request includes any necessary API keys or authentication headers as required by your Trigger.dev setup. - Sign the JWT Directly Using
jose: Once you have the claims, you'll use thejoselibrary to sign these claims and generate a valid JWT. This process involves specifying the algorithm (e.g.,HS256orRS256), providing a private key or secret, and then usingjose's signing functions to create the token. This is the exact cryptographic process that the SDK would perform internally, but we're doing it explicitly in our application.
This manual process allows you to generate public tokens or perform other authenticated actions without ever touching the @trigger.dev/sdk's Zod-dependent validation path. The success of this workaround strongly confirms the root cause of the problem: the Trigger.dev API is working correctly, and the issue is strictly a Zod v4 compatibility problem within the @trigger.dev/core SDK's client-side validation logic that utilizes zod-validation-error. While this workaround provides immediate relief and unblocks your development, it's important to remember that it's a temporary solution. It means you're duplicating logic that the SDK is designed to handle, which can be less ergonomic and might require more manual maintenance if the Trigger.dev API changes. However, for critical projects facing a hard stop due to this Zod v4 issue, it's an invaluable tool to keep things moving. We still advocate for the official SDK fix, but this direct API call approach is a solid fallback for urgent needs, providing tangible value by allowing your application to connect to Trigger.dev without any Zod-related errors.
The Curious Case: Why It Works Locally, But Fails in Production
One of the most perplexing aspects of this Zod v4 compatibility issue is its inconsistent behavior across environments. Many developers, including us, have noticed that the problem consistently reproduces in production environments (e.g., Docker containers running Alpine Linux with Bun or Node.js) but mysteriously works perfectly fine locally during development. This dichotomy can be incredibly frustrating and misleading, making it even harder to pinpoint the root cause. This section will delve into the nuances of dependency management and environment differences that can explain this peculiar behavior, offering additional context to this puzzling scenario.
Understanding Dependency Hoisting and Bundling:
The primary reason for this local-vs-production discrepancy often lies in how package managers (like npm, yarn, pnpm) handle node_modules in different contexts, and how build tools (like Webpack, Next.js, Bun) bundle code for deployment:
- Local Development (Hoisting/Symlinking): During local development, package managers aggressively hoist common dependencies to the top-level
node_modulesdirectory or use symlinks (especiallypnpm). This can sometimes lead to a situation where@trigger.dev/core'szod-validation-error@^1.5.0might inadvertently resolve to the project's Zod v3 dependency, or perhaps a more complexinstanceofcheck fails due to multiple Zod instances, but the specifict.valueType._zodaccess somehow doesn't trigger the error. It's possible that the Zod v3 version is picked up byzod-validation-errorduring local execution due to the way dependencies are resolved, preventing the crash. The flexibility and caching of local environments can sometimes mask deeper compatibility problems. - Production Environments (Strict Bundling/Flattening): In production, especially with Docker and optimized build processes (like those in Next.js or Bun deployments), dependencies are often more strictly flattened or bundled. The build process might aggressively deduplicate packages, or the runtime environment's module resolution might be less forgiving. In these scenarios, if your project explicitly uses
zod@^4.2.1, it's much more likely that the single Zod v4 instance is the one provided throughout the application, including tozod-validation-error@^1.5.0within@trigger.dev/core. Whenzod-validation-errorthen tries to access_zodon a Zod v4 schema, theTypeErrorpredictably occurs. The isolated nature of containerized environments or specific runtime behaviors (like how Bun handles module resolution compared to Node.js) can expose these underlying Zod v4 compatibility issues that were previously hidden by local development quirks.
instanceof Checks and Module Boundaries:
Another factor could be related to instanceof checks across different module boundaries. If, by some chance, different versions of Zod are loaded in separate bundles or contexts, an instanceof check might fail even if the underlying object looks like a Zod schema. However, in this specific case, the TypeError: undefined is not an object points more directly to a missing property (_zod) rather than a type mismatch across contexts.
Ultimately, while the local environment might offer a temporary illusion of functionality, the core Zod v4 compatibility issue remains. The behavior difference merely highlights the fragility of relying on specific dependency resolution behaviors that aren't guaranteed across all environments. The consistent failure in production is the definitive signal that a fundamental version incompatibility exists, reinforcing the need for the proposed solution to update zod-validation-error to its Zod v4-compatible version within @trigger.dev/core. Understanding these environment-specific nuances adds another layer of appreciation for robust dependency management and consistent behavior across all deployment stages.
Conclusion: Navigating Zod and Trigger.dev Together
We've taken quite a journey through the complexities of Zod v4 compatibility with @trigger.dev/core, from encountering the misleading TriggerApiError: Connection error. to unraveling the TypeError rooted in zod-validation-error's reliance on outdated Zod v3 internals. It's clear that while both Zod and Trigger.dev are incredibly powerful tools for modern JavaScript development, integrating them sometimes requires a deep dive into their dependency trees. The good news is that the solution is straightforward: updating @trigger.dev/core to use a Zod v4-compatible version of zod-validation-error (specifically ^4.0.1 or later) will resolve this conflict, ensuring smooth operation.
For those needing immediate relief, our direct API call workaround using jose provides a robust, albeit temporary, solution to bypass the problematic SDK validation. This strategy not only unblocks your development but also definitively confirms the root cause of the Zod v4 compatibility issue: the problem lies within the SDK's internal dependency management, not the Trigger.dev API itself. Furthermore, understanding why this issue might manifest differently between local and production environments highlights the critical importance of consistent dependency resolution and thorough testing across all deployment stages.
As the JavaScript ecosystem continues to evolve rapidly, maintaining dependency compatibility is a constant challenge. This experience serves as a valuable reminder that even when peer dependencies seem to allow for broader compatibility, direct dependencies can introduce hidden conflicts. By implementing the proposed update to zod-validation-error in @trigger.dev/core, developers can confidently leverage the latest features of Zod v4 alongside Trigger.dev, building robust and reliable serverless applications without unnecessary headaches.
We hope this comprehensive guide helps you resolve any Zod v4 compatibility issues you might be facing and empowers you to build even better applications. Happy coding!
For further reading and insights into the tools mentioned, check out these trusted resources:
- Learn more about Zod, a TypeScript-first schema declaration and validation library, at its official documentation: https://zod.dev/
- Explore the
zod-validation-errorlibrary and its updates, including Zod v4 compatibility, on its GitHub repository: https://github.com/causaly/zod-validation-error - Understand more about JSON Web Signatures (JWS) and the
joselibrary: https://www.npmjs.com/package/jose - Dive deeper into dependency management in Node.js projects and best practices: https://docs.npmjs.com/about-npm/dependency-types