fabian-hiller / valibot

The modular and type safe schema library for validating structural data 🤖
https://valibot.dev
MIT License
6k stars 186 forks source link

Type of ValiError.issues #693

Closed peterbe closed 3 months ago

peterbe commented 3 months ago

If I do:

try {
  const stuff = v.parse(MyObjSchema, parsedExternalData)
} catch (error)  {
  throw error
}

it will print something like this:

ValiError: Invalid type: Expected boolean but received undefined
    at Object.parse (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/valibot/dist/index.cjs:5461:11)
    at loader5 (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/app/routes/plog.$.tsx:86:34)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Object.callRouteLoader (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/@remix-run/server-runtime/dist/data.js:66:16)
    at <anonymous> (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/@remix-run/router/router.ts:4770:21)
    at callLoaderOrAction (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/@remix-run/router/router.ts:4832:16)
    at async Promise.all (index 1)
    at callDataStrategyImpl (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/@remix-run/router/router.ts:4673:17)
    at callDataStrategy (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/@remix-run/router/router.ts:3928:19)
    at loadRouteData (/Users/peterbe/dev/PETERBECOM/remix-peterbecom/node_modules/@remix-run/router/router.ts:3872:19) {
  issues: [
    {
      kind: 'schema',
      type: 'boolean',
      input: undefined,
      expected: 'boolean',
      received: 'undefined',
      message: 'Invalid type: Expected boolean but received undefined',
      requirement: undefined,
      path: [Array],
      issues: undefined,
      lang: undefined,
      abortEarly: undefined,
      abortPipeEarly: undefined
    }
  ]
}

Nowhere in that thrown error does it say what key in the parsed object that was causing the Expected boolean but received undefined. I can sort of figure that out by doing this instead:

try {
  const stuff = v.parse(MyObjSchema, parsedExternalData)
} catch (error)  {
   if (error instanceof v.ValiError) {
      console.error(
        "Validation issue in", error.issues[0]
      );
    }
  throw error
}

Now, I can see, before the error throws that apparently it's in .post.hide_comments. Ah! That's what I wanted/needed to know. In fact, it prints:

Validation issue in {
  kind: 'schema',
  type: 'boolean',
  input: undefined,
  expected: 'boolean',
  received: 'undefined',
  message: 'Invalid type: Expected boolean but received undefined',
  requirement: undefined,
  path: [
    {
      type: 'object',
      origin: 'value',
      input: [Object],
      key: 'post',
      value: [Object]
    },
    {
      type: 'object',
      origin: 'value',
      input: [Object],
      key: 'hide_comments',
      value: undefined
    }
  ],
  issues: undefined,
  lang: undefined,
  abortEarly: undefined,
  abortPipeEarly: undefined
}

By why is the error.issues[0].path of type any[]? Now I get a TS error on this:

VS Code TS error

Perhaps I'm missing something obvious but figuring out which key in my object schema the error was about was very hard.

fabian-hiller commented 3 months ago

Nowhere in that thrown error does it say what key in the parsed object that was causing the Expected boolean but received undefined.

This information can be found under the .path key of each issue. Your console just doesn't show it all, but that's out of our control. The data is there.

By why is the error.issues[0].path of type any[]?

Something is wrong here, but everything looks fine on my machine. What version of Valibot are you using? Can you share your schema and the shown code with me?

Perhaps I'm missing something obvious but figuring out which key in my object schema the error was about was very hard.

You can also pass the issue to v.getDotPath<TSchema>(issue) to get its path.

foster-hangdaan commented 3 months ago

I have a similar issue when trying to access the path key within a ValiError. I am getting some options but key is not one of them:

image

I am using Valibot v0.35.0.

fabian-hiller commented 3 months ago

This is because not every path item has a .key property, but I plan to improve the developer experience on this part by adding key: undefined in this case.

fabian-hiller commented 3 months ago

v0.36.0 is available

peterbe commented 2 months ago

So trick is, use:

  } catch (error) {
    if (v.isValiError(error)) {

not

  } catch (error) {
    if (error instanceof v.ValiError) {
fabian-hiller commented 2 months ago

Yes, but even better is: v.isValiError<typeof Schema>(error)