Unable to use `zod` in coda packs (: e=>{this.issues=[...this.issues,e]} could not be cloned.)

I’m getting an error that looks like this while trying to use zod to validate incoming json. I have mostly identified the issue down to usage of transforms, but can’t be 100% sure

e=>{this.issues=[...this.issues,e]} could not be cloned.

It’s really hard to debug coda packs because I cannot reproduce the problem on my local computer. is there a way to reproduce coda pack’s runtime environment?

It’s not a perfect emulation, but when you run coda execute with the flag --vm=true it will run the code in a virtual machine that’s very close to the Packs runtime. When you install the SDK it attempts to install the isolated-vm dependency. If that succeeds it will use the VM, but if that fails it will silently fall back to running on Node directly. The isolated-vm dependency has a lot of system requirements, as outlined here:

Gotcha. Do you have an idea what the root cause of “object cannot be cloned” issue is?

Not exactly. Looking through the issues in the isolated-vm repo it seems like it could be related to restrictions on their end. I created a Pack that did some very simple Zod validation and it seemed to work fine when uploaded:

import * as coda from "@codahq/packs-sdk";
import { z } from "zod";

export const pack = coda.newPack();

pack.addFormula({
  name: "Test",
  description: "",
  parameters: [],
  resultType: coda.ValueType.String,
  execute: async function(args, context) {
    let response = await context.fetcher.fetch({
      method: "GET",
      url: "https://httpbin.org/get",
    });
    let data = response.body;
    const schema = z.object({
      headers: z.object({
        Accept: z.string(),
      }),
    });
    schema.parse(data);
    return "Done";
  },
});

pack.addNetworkDomain("httpbin.org");

Perhaps there is a specific feature of Zod causing this error?

It works fine when the validation succeeds, it’s when it fails that it breaks.

Ah, indeed! It looks like our runtime has an issue serializing functions in some cases. I’ll report that to the engineering team, but in the meantime you can work around this issue by stripping functions from the exceptions before they are thrown. Here’s an example using the onError property of the formula to define a generic error handler:

import * as coda from "@codahq/packs-sdk";
import { z } from "zod";

export const pack = coda.newPack();

pack.addFormula({
  name: "Test",
  description: "",
  parameters: [],
  resultType: coda.ValueType.String,
  onError: handleError,
  execute: async function(args, context) {
    let response = await context.fetcher.fetch({
      method: "GET",
      url: "https://httpbin.org/get",
    });
    let data = response.body;
    const schema = z.object({
      headers: z.object({
        Accept: z.number(),
      }),
    });
    schema.parse(data);
    return "Done";
  },
});

function handleError(e) {
  for (let key of Object.keys(e)) {
    let value = e[key];
    if (typeof value == "function") {
      delete e[key];
    }
  }
  throw e;
}

Sweet, thanks so much for this!