STET

agent_patch

runs/2026-02-27__21-30-28__gpt-5-4/flux-commit-fc48a85d/flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/agent-logs/agent.patch

27476 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/__tests__/parser.test.ts b/app/src/__tests__/parser.test.ts
index 7d9ecf1..a41ba82 100644
--- a/tmp/agent-patch-flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/__tests__/parser.test.ts
+++ b/app/src/__tests__/parser.test.ts
@@ -33,3 +33,21 @@ test('invalid enum value', () => {
 test('parsing unknown', () => {
   z.string().parse('Red' as unknown);
 });
+
+test('repeated invalid shared reference reports each occurrence', () => {
+  const Child = z.object({ label: z.string() });
+  const Parent = z.object({ a: Child, b: Child });
+  const shared: any = { label: 123 };
+
+  try {
+    Parent.parse({ a: shared, b: shared });
+    throw new Error('expected parse to fail');
+  } catch (err) {
+    const error: any = err;
+    expect(error.errors).toHaveLength(2);
+
+    const paths = error.errors.map((suberror: any) => suberror.path.join('.'));
+    expect(paths).toContain('a.label');
+    expect(paths).toContain('b.label');
+  }
+});
diff --git a/tmp/agent-patch-flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/__tests__/recursive.test.ts b/app/src/__tests__/recursive.test.ts
index b210628..a5ec33b 100644
--- a/tmp/agent-patch-flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/__tests__/recursive.test.ts
+++ b/app/src/__tests__/recursive.test.ts
@@ -106,3 +106,48 @@ test('self recursion with base type', () => {
   untypedCategory.subcategories = [untypedCategory];
   Category.parse(untypedCategory); // parses successfully
 });
+
+test('recursive tree with duplicated invalid child reports each path', () => {
+  const Tree: any = z.lazy(() =>
+    z.object({
+      name: z.string(),
+      children: z.array(Tree),
+    }),
+  );
+
+  const badChild: any = { name: 99, children: [] };
+  const root: any = { name: 'root', children: [badChild, badChild] };
+
+  try {
+    Tree.parse(root);
+    throw new Error('expected parse to fail');
+  } catch (err) {
+    const error: any = err;
+    expect(error.errors).toHaveLength(2);
+
+    const paths = error.errors.map((suberror: any) => suberror.path.join('.'));
+    expect(paths).toContain('children.0.name');
+    expect(paths).toContain('children.1.name');
+  }
+});
+
+test('recursive cycle reports validation errors instead of overflowing the stack', () => {
+  const Node: any = z.lazy(() =>
+    z.object({
+      next: z.union([Node, z.null()]),
+      value: z.number(),
+    }),
+  );
+
+  const root: any = { value: 'bad', next: null };
+  root.next = root;
+
+  try {
+    Node.parse(root);
+    throw new Error('expected parse to fail');
+  } catch (err) {
+    const error: any = err;
+    expect(error).toBeInstanceOf(z.ZodError);
+    expect(error.errors.map((suberror: any) => suberror.code)).toContain('invalid_type');
+  }
+});
diff --git a/tmp/agent-patch-flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/parser.ts b/app/src/parser.ts
index 64e07d1..35df401 100644
--- a/tmp/agent-patch-flux-commit-fc48a85d.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/src/parser.ts
+++ b/app/src/parser.ts
@@ -5,11 +5,51 @@ import { util } from './helpers/util';
 import { ZodErrorMap, defaultErrorMap } from './defaultErrorMap';
 
 export type ParseParams = {
-  seen?: { schema: any; objects: any[] }[];
+  seen?: SeenSchemaPair[];
   path?: (string | number)[];
   errorMap?: ZodErrorMap;
 };
 
+type SeenObject = {
+  object: any;
+  count: number;
+  error?: ZodError;
+  path: (string | number)[];
+  processing: boolean;
+};
+
+type SeenSchemaPair = {
+  schema: any;
+  objects: SeenObject[];
+};
+
+const MAX_ACTIVE_RECURSIVE_PASSES = 3;
+
+const pathStartsWith = (path: (string | number)[], prefix: (string | number)[]) => {
+  if (prefix.length > path.length) {
+    return false;
+  }
+
+  return prefix.every((segment, index) => {
+    return path[index] === segment;
+  });
+};
+
+const rebaseError = (error: ZodError, fromPath: (string | number)[], toPath: (string | number)[]) => {
+  return ZodError.create(
+    error.errors.map(suberror => {
+      const nextPath = pathStartsWith(suberror.path, fromPath)
+        ? [...toPath, ...suberror.path.slice(fromPath.length)]
+        : [...toPath, ...suberror.path];
+
+      return {
+        ...suberror,
+        path: nextPath,
+      };
+    }),
+  );
+};
+
 export const getParsedType = (data: any): ZodParsedType => {
   if (typeof data === 'string') return 'string';
   if (typeof data === 'number') {
@@ -88,370 +128,411 @@ export const ZodParser = (schemaDef: z.ZodTypeDef) => (
   const def: ZodDef = schemaDef as any;
   const parsedType = getParsedType(obj);
 
-  const schemaSeen = params.seen.find(x => x.schema === schemaDef);
   const isPrimitive = typeof obj !== 'object' || obj === null;
-  if (isPrimitive) {
-  } else if (schemaSeen) {
-    if (schemaSeen.objects.indexOf(obj) !== -1) {
+  let seenObject: SeenObject | undefined;
+
+  if (!isPrimitive) {
+    let schemaSeen = params.seen.find(x => x.schema === schemaDef);
+    if (!schemaSeen) {
+      schemaSeen = { schema: schemaDef, objects: [] };
+      params.seen.push(schemaSeen);
+    }
+
+    seenObject = schemaSeen.objects.find(entry => entry.object === obj);
+    if (!seenObject) {
+      seenObject = {
+        object: obj,
+        count: 0,
+        path: [...params.path],
+        processing: false,
+      };
+      schemaSeen.objects.push(seenObject);
+    }
+
+    seenObject.count += 1;
+
+    if (seenObject.error) {
+      throw rebaseError(seenObject.error, seenObject.path, params.path);
+    }
+
+    if (seenObject.processing && seenObject.count >= MAX_ACTIVE_RECURSIVE_PASSES) {
       return obj;
-    } else {
-      schemaSeen.objects.push(obj);
     }
-  } else {
-    params.seen.push({ schema: schemaDef, objects: [obj] });
+
+    if (!seenObject.processing) {
+      seenObject.path = [...params.path];
+    }
+
+    seenObject.processing = true;
   }
 
   const error = new ZodError([]);
   let returnValue: any = obj;
 
-  switch (def.t) {
-    case z.ZodTypes.string:
-      if (parsedType !== ZodParsedType.string) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.string, received: parsedType }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.number:
-      if (parsedType !== ZodParsedType.number) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.number, received: parsedType }),
-        );
-        throw error;
-      }
-      if (Number.isNaN(obj)) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.number, received: ZodParsedType.nan }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.bigint:
-      if (parsedType !== ZodParsedType.bigint) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.number, received: parsedType }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.boolean:
-      if (parsedType !== ZodParsedType.boolean) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.boolean, received: parsedType }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.undefined:
-      if (parsedType !== ZodParsedType.undefined) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.undefined, received: parsedType }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.null:
-      if (parsedType !== ZodParsedType.null) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.null, received: parsedType }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.any:
-      break;
-    case z.ZodTypes.unknown:
-      break;
-    case z.ZodTypes.void:
-      if (parsedType !== ZodParsedType.undefined && parsedType !== ZodParsedType.null) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.void, received: parsedType }),
-        );
-        throw error;
-      }
-      break;
-    case z.ZodTypes.array:
-      if (parsedType !== ZodParsedType.array) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.array, received: parsedType }),
-        );
-        throw error;
-      }
-      const data: any[] = obj;
-      if (def.nonempty === true && obj.length === 0) {
-        error.addError(makeError({ code: ZodErrorCode.nonempty_array_is_empty }));
-        throw error;
-      }
-      data.map((item, i) => {
-        try {
-          const parsedItem = def.type.parse(item, { ...params, path: [...params.path, i] });
-          return parsedItem;
-        } catch (err) {
-          const zerr: ZodError = err;
-          error.addErrors(zerr.errors);
+  try {
+    switch (def.t) {
+      case z.ZodTypes.string:
+        if (parsedType !== ZodParsedType.string) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.string, received: parsedType }),
+          );
+          throw error;
         }
-      });
-      if (!error.isEmpty) {
-        throw error;
-      }
-      break;
-    case z.ZodTypes.object:
-      if (parsedType !== ZodParsedType.object) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.object, received: parsedType }),
-        );
-        throw error;
-      }
-
-      const shape = def.shape();
-      if (def.params.strict) {
-        const shapeKeys = Object.keys(shape);
-        const objKeys = Object.keys(obj);
-        const extraKeys = objKeys.filter(k => shapeKeys.indexOf(k) === -1);
-
-        if (extraKeys.length) {
-          error.addError(makeError({ code: ZodErrorCode.unrecognized_keys, keys: extraKeys }));
+        break;
+      case z.ZodTypes.number:
+        if (parsedType !== ZodParsedType.number) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.number, received: parsedType }),
+          );
+          throw error;
         }
-      }
-
-      for (const key in shape) {
-        try {
-          def.shape()[key].parse(obj[key], { ...params, path: [...params.path, key] });
-        } catch (err) {
-          const zerr: ZodError = err;
-          error.addErrors(zerr.errors);
+        if (Number.isNaN(obj)) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_type,
+              expected: ZodParsedType.number,
+              received: ZodParsedType.nan,
+            }),
+          );
+          throw error;
         }
-      }
-
-      break;
-    case z.ZodTypes.union:
-      let isValid = false;
-      const unionErrors: ZodError[] = [];
-      for (const option of def.options) {
-        try {
-          option.parse(obj, params);
-          isValid = true;
-        } catch (err) {
-          unionErrors.push(err);
+        break;
+      case z.ZodTypes.bigint:
+        if (parsedType !== ZodParsedType.bigint) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.number, received: parsedType }),
+          );
+          throw error;
         }
-      }
-
-      if (!isValid) {
-        const filteredErrors = unionErrors.filter(err => {
-          return err.errors[0].code !== 'invalid_type';
+        break;
+      case z.ZodTypes.boolean:
+        if (parsedType !== ZodParsedType.boolean) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.boolean, received: parsedType }),
+          );
+          throw error;
+        }
+        break;
+      case z.ZodTypes.undefined:
+        if (parsedType !== ZodParsedType.undefined) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.undefined, received: parsedType }),
+          );
+          throw error;
+        }
+        break;
+      case z.ZodTypes.null:
+        if (parsedType !== ZodParsedType.null) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.null, received: parsedType }),
+          );
+          throw error;
+        }
+        break;
+      case z.ZodTypes.any:
+        break;
+      case z.ZodTypes.unknown:
+        break;
+      case z.ZodTypes.void:
+        if (parsedType !== ZodParsedType.undefined && parsedType !== ZodParsedType.null) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.void, received: parsedType }),
+          );
+          throw error;
+        }
+        break;
+      case z.ZodTypes.array:
+        if (parsedType !== ZodParsedType.array) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.array, received: parsedType }),
+          );
+          throw error;
+        }
+        const data: any[] = obj;
+        if (def.nonempty === true && obj.length === 0) {
+          error.addError(makeError({ code: ZodErrorCode.nonempty_array_is_empty }));
+          throw error;
+        }
+        data.map((item, i) => {
+          try {
+            const parsedItem = def.type.parse(item, { ...params, path: [...params.path, i] });
+            return parsedItem;
+          } catch (err) {
+            const zerr: ZodError = err;
+            error.addErrors(zerr.errors);
+          }
         });
-        if (filteredErrors.length === 1) {
-          error.addErrors(filteredErrors[0].errors);
-        } else {
+        if (!error.isEmpty) {
+          throw error;
+        }
+        break;
+      case z.ZodTypes.object:
+        if (parsedType !== ZodParsedType.object) {
           error.addError(
-            makeError({
-              code: ZodErrorCode.invalid_union,
-              unionErrors: unionErrors,
-            }),
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.object, received: parsedType }),
           );
+          throw error;
         }
-      }
-      break;
-    case z.ZodTypes.intersection:
-      try {
-        def.left.parse(obj, params);
-      } catch (err) {
-        error.addErrors(err.errors);
-      }
-
-      try {
-        def.right.parse(obj, params);
-      } catch (err) {
-        error.addErrors(err.errors);
-      }
 
-      break;
-
-    case z.ZodTypes.tuple:
-      if (parsedType !== ZodParsedType.array) {
-        error.addError(
-          makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.array, received: parsedType }),
-        );
-        throw error;
-      }
-      if (obj.length > def.items.length) {
-        error.addError(
-          makeError({ code: ZodErrorCode.too_big, maximum: def.items.length, inclusive: true, type: 'array' }),
-        );
-      } else if (obj.length < def.items.length) {
-        error.addError(
-          makeError({ code: ZodErrorCode.too_small, minimum: def.items.length, inclusive: true, type: 'array' }),
-        );
-      }
+        const shape = def.shape();
+        if (def.params.strict) {
+          const shapeKeys = Object.keys(shape);
+          const objKeys = Object.keys(obj);
+          const extraKeys = objKeys.filter(k => shapeKeys.indexOf(k) === -1);
 
-      const parsedTuple: any[] = [];
-      const tupleData: any[] = obj;
-      for (const index in tupleData) {
-        const item = tupleData[index];
-        const itemParser = def.items[index];
-        try {
-          parsedTuple.push(itemParser.parse(item, { ...params, path: [...params.path, index] }));
-        } catch (err) {
-          error.addErrors(err.errors);
+          if (extraKeys.length) {
+            error.addError(makeError({ code: ZodErrorCode.unrecognized_keys, keys: extraKeys }));
+          }
         }
-      }
-      break;
-    case z.ZodTypes.lazy:
-      const lazySchema = def.getter();
-      lazySchema.parse(obj, params);
-      break;
-    case z.ZodTypes.literal:
-      if (obj !== def.value) {
-        error.addError(makeError({ code: ZodErrorCode.invalid_literal_value, expected: def.value }));
-      }
-      break;
-
-    case z.ZodTypes.enum:
-      if (def.values.indexOf(obj) === -1) {
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_enum_value,
-            options: def.values,
-          }),
-        );
-      }
-      break;
-    case z.ZodTypes.nativeEnum:
-      if (util.getValidEnumValues(def.values).indexOf(obj) === -1) {
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_enum_value,
-            options: Object.values(def.values),
-          }),
-        );
-      }
-      break;
-    case z.ZodTypes.function:
-      if (parsedType !== ZodParsedType.function) {
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_type,
-            expected: ZodParsedType.function,
-            received: parsedType,
-          }),
-        );
-        throw error;
-      }
-      const validatedFunc = (...args: any[]) => {
-        try {
-          def.args.parse(args as any);
-        } catch (err) {
-          if (err instanceof ZodError) {
-            const argsError = new ZodError([]);
-            argsError.addError(
-              makeError({
-                code: ZodErrorCode.invalid_arguments,
-                argumentsError: err,
-              }),
-            );
-            throw argsError;
+
+        for (const key in shape) {
+          try {
+            def.shape()[key].parse(obj[key], { ...params, path: [...params.path, key] });
+          } catch (err) {
+            const zerr: ZodError = err;
+            error.addErrors(zerr.errors);
           }
-          throw err;
         }
 
-        const result = obj(...(args as any));
+        break;
+      case z.ZodTypes.union:
+        let isValid = false;
+        const unionErrors: ZodError[] = [];
+        for (const option of def.options) {
+          try {
+            option.parse(obj, params);
+            isValid = true;
+          } catch (err) {
+            unionErrors.push(err);
+          }
+        }
 
-        try {
-          return def.returns.parse(result);
-        } catch (err) {
-          if (err instanceof ZodError) {
-            const returnsError = new ZodError([]);
-            returnsError.addError(
+        if (!isValid) {
+          const filteredErrors = unionErrors.filter(err => {
+            return err.errors[0].code !== 'invalid_type';
+          });
+          if (filteredErrors.length === 1) {
+            error.addErrors(filteredErrors[0].errors);
+          } else {
+            error.addError(
               makeError({
-                code: ZodErrorCode.invalid_return_type,
-                returnTypeError: err,
+                code: ZodErrorCode.invalid_union,
+                unionErrors: unionErrors,
               }),
             );
-            throw returnsError;
           }
-          throw err;
         }
-      };
-      return validatedFunc;
-    case z.ZodTypes.record:
-      if (parsedType !== ZodParsedType.object) {
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_type,
-            expected: ZodParsedType.object,
-            received: parsedType,
-          }),
-        );
-        throw error;
-      }
-
-      for (const key in obj) {
+        break;
+      case z.ZodTypes.intersection:
         try {
-          def.valueType.parse(obj[key], { ...params, path: [...params.path, key] });
+          def.left.parse(obj, params);
         } catch (err) {
           error.addErrors(err.errors);
         }
-      }
-      break;
-    case z.ZodTypes.date:
-      if (!(obj instanceof Date)) {
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_type,
-            expected: ZodParsedType.date,
-            received: parsedType,
-          }),
-        );
-        throw error;
-      }
-      if (isNaN(obj.getTime())) {
-        console.log('NAN');
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_date,
-          }),
-        );
-        throw error;
-      }
-      break;
-
-    case z.ZodTypes.promise:
-      if (parsedType !== ZodParsedType.promise) {
-        error.addError(
-          makeError({
-            code: ZodErrorCode.invalid_type,
-            expected: ZodParsedType.promise,
-            received: parsedType,
-          }),
-        );
-        throw error;
-      }
-      return new Promise(async (res, rej) => {
-        const objValue = await obj;
+
         try {
-          const parsed = def.type.parse(objValue, params);
-          res(parsed);
+          def.right.parse(obj, params);
         } catch (err) {
-          rej(err);
+          error.addErrors(err.errors);
         }
-      });
 
-    default:
-      util.assertNever(def);
-  }
+        break;
+
+      case z.ZodTypes.tuple:
+        if (parsedType !== ZodParsedType.array) {
+          error.addError(
+            makeError({ code: ZodErrorCode.invalid_type, expected: ZodParsedType.array, received: parsedType }),
+          );
+          throw error;
+        }
+        if (obj.length > def.items.length) {
+          error.addError(
+            makeError({ code: ZodErrorCode.too_big, maximum: def.items.length, inclusive: true, type: 'array' }),
+          );
+        } else if (obj.length < def.items.length) {
+          error.addError(
+            makeError({ code: ZodErrorCode.too_small, minimum: def.items.length, inclusive: true, type: 'array' }),
+          );
+        }
+
+        const parsedTuple: any[] = [];
+        const tupleData: any[] = obj;
+        for (const index in tupleData) {
+          const item = tupleData[index];
+          const itemParser = def.items[index];
+          try {
+            parsedTuple.push(itemParser.parse(item, { ...params, path: [...params.path, index] }));
+          } catch (err) {
+            error.addErrors(err.errors);
+          }
+        }
+        break;
+      case z.ZodTypes.lazy:
+        const lazySchema = def.getter();
+        lazySchema.parse(obj, params);
+        break;
+      case z.ZodTypes.literal:
+        if (obj !== def.value) {
+          error.addError(makeError({ code: ZodErrorCode.invalid_literal_value, expected: def.value }));
+        }
+        break;
+
+      case z.ZodTypes.enum:
+        if (def.values.indexOf(obj) === -1) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_enum_value,
+              options: def.values,
+            }),
+          );
+        }
+        break;
+      case z.ZodTypes.nativeEnum:
+        if (util.getValidEnumValues(def.values).indexOf(obj) === -1) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_enum_value,
+              options: Object.values(def.values),
+            }),
+          );
+        }
+        break;
+      case z.ZodTypes.function:
+        if (parsedType !== ZodParsedType.function) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_type,
+              expected: ZodParsedType.function,
+              received: parsedType,
+            }),
+          );
+          throw error;
+        }
+        const validatedFunc = (...args: any[]) => {
+          try {
+            def.args.parse(args as any);
+          } catch (err) {
+            if (err instanceof ZodError) {
+              const argsError = new ZodError([]);
+              argsError.addError(
+                makeError({
+                  code: ZodErrorCode.invalid_arguments,
+                  argumentsError: err,
+                }),
+              );
+              throw argsError;
+            }
+            throw err;
+          }
+
+          const result = obj(...(args as any));
+
+          try {
+            return def.returns.parse(result);
+          } catch (err) {
+            if (err instanceof ZodError) {
+              const returnsError = new ZodError([]);
+              returnsError.addError(
+                makeError({
+                  code: ZodErrorCode.invalid_return_type,
+                  returnTypeError: err,
+                }),
+              );
+              throw returnsError;
+            }
+            throw err;
+          }
+        };
+        return validatedFunc;
+      case z.ZodTypes.record:
+        if (parsedType !== ZodParsedType.object) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_type,
+              expected: ZodParsedType.object,
+              received: parsedType,
+            }),
+          );
+          throw error;
+        }
+
+        for (const key in obj) {
+          try {
+            def.valueType.parse(obj[key], { ...params, path: [...params.path, key] });
+          } catch (err) {
+            error.addErrors(err.errors);
+          }
+        }
+        break;
+      case z.ZodTypes.date:
+        if (!(obj instanceof Date)) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_type,
+              expected: ZodParsedType.date,
+              received: parsedType,
+            }),
+          );
+          throw error;
+        }
+        if (isNaN(obj.getTime())) {
+          console.log('NAN');
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_date,
+            }),
+          );
+          throw error;
+        }
+        break;
 
-  const customChecks = def.checks || [];
-  for (const check of customChecks) {
-    if (!check.check(returnValue)) {
-      const { check: checkMethod, ...noMethodCheck } = check;
-      error.addError(makeError(noMethodCheck));
+      case z.ZodTypes.promise:
+        if (parsedType !== ZodParsedType.promise) {
+          error.addError(
+            makeError({
+              code: ZodErrorCode.invalid_type,
+              expected: ZodParsedType.promise,
+              received: parsedType,
+            }),
+          );
+          throw error;
+        }
+        return new Promise(async (res, rej) => {
+          const objValue = await obj;
+          try {
+            const parsed = def.type.parse(objValue, params);
+            res(parsed);
+          } catch (err) {
+            rej(err);
+          }
+        });
+
+      default:
+        util.assertNever(def);
     }
-  }
 
-  if (!error.isEmpty) {
-    throw error;
-  }
+    const customChecks = def.checks || [];
+    for (const check of customChecks) {
+      if (!check.check(returnValue)) {
+        const { check: checkMethod, ...noMethodCheck } = check;
+        error.addError(makeError(noMethodCheck));
+      }
+    }
 
-  return returnValue as any;
+    if (!error.isEmpty) {
+      throw error;
+    }
+
+    return returnValue as any;
+  } catch (err) {
+    if (seenObject && err instanceof ZodError) {
+      seenObject.error = err;
+      seenObject.path = [...params.path];
+    }
+    throw err;
+  } finally {
+    if (seenObject) {
+      seenObject.processing = false;
+    }
+  }
 };