Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZodError#message cannot deal with circular data structures in its issues #3422

Open
jandockx opened this issue Apr 19, 2024 · 1 comment
Open
Labels

Comments

@jandockx
Copy link
Contributor

Example

A Mocha test that shows the issue:

/* eslint-env mocha */

const { z, ZodError } = require('zod')

describe('zod', function () {
  it('cannot deal with circular data structures', function () {
    const AnObjectSchema = z.object({ someLiteralProperty: z.literal(1) })

    const cicrularObject = {
      aProperty: 'a property',
      anotherProperty: 137,
      anObjectProperty: { anObjectPropertyProperty: 'an object property property' },
      anArrayProperty: [{ anArrayObjectPropertyProperty: 'an object property property' }]
    }
    cicrularObject.anObjectProperty.cicrularObject = cicrularObject
    cicrularObject.anArrayProperty.push(cicrularObject.anObjectProperty)
    const violatingObject = { someLiteralProperty: cicrularObject }

    const { success, error } = AnObjectSchema.safeParse(violatingObject)

    success.should.be.false()
    error.should.be.an.instanceof(ZodError)
    error.message.should.be.a.String()
  })
})

This test fails with

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Object'
    |     property 'anObjectProperty' -> object with constructor 'Object'
    --- property 'cicrularObject' closes the circle
    at JSON.stringify (<anonymous>)
    at get message [as message] (node_modules/zod/lib/ZodError.js:105:21)
    at Context.<anonymous> (test/00.zodIssue.js:23:11)
    at process.processImmediate (node:internal/timers:478:21)

Analysis

ZodError.ts, line 283:

  get message() {
    return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
  }

JSON.stringify is called on this.issues. JSON.stringify cannot cope with circular data structures. In the example, the circular data structure appears in the received property of the issue.

jsonStringifyReplacer does not deal with this either:

helpers/util.ts#jsonStringifyReplacer, line 91:

  export const jsonStringifyReplacer = (_: string, value: any): any => {
    if (typeof value === "bigint") {
      return value.toString();
    }
    return value;
  };
@colinhacks
Copy link
Owner

Good catch. For security reasons, Zod isn't supposed to print the input data when it throws an error...but you've found the exception here with ZodInvalidLiteralIssue. This will be fixed in Zod 4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants