#convex dev 400, schema error

48 messages · Page 1 of 1 (latest)

devout meteor
#
Analyzing and deploying source code...
✖ Error: Unable to push deployment config to <dev-url>
400 Bad Request: Error: Hit an error while pushing:
Uncaught TypeError: Cannot read properties of undefined (reading 'json')

The code it's referencing is from validator.ts - the error is specifically where v.json is being asssigned to fieldType - v is undefined:

  object<T extends PropertyValidators>(schema: T): ObjectValidator<T> {
    return new Validator(
      {
        type: "object",
        value: Object.fromEntries(
          Object.entries(schema).map(([k, v]) => [
            k,
            { fieldType: v.json, optional: v.optional },
          ])
        ),
      },
      false
    );
  },

I've pored over my schema and can't find any undefined values. The only place I can even think of that could cause this is maybe mispelling a table name in v.id(), but I'm not even certain that would result in undefined.

Pretty stuck here, any help greatly appreciated.

topaz breach
#

Looks like the v in map(([k, v]) is shadowing the variable

devout meteor
#

Oh is v.json trying to reference the outer v?

#

I'd expect every deployment to be broken though, this is in convex source - not sure why it would have limited impact

topaz breach
#

oh sorry I was thinking this was your code, didn't read carefully

#

What's your schema look like, is it possible you have an entry in there that is undefined?

devout meteor
#

I've been troubleshooting for about an hour and am blocked due to not getting logs - I'm guessing this is running on convex's side and logs are obfuscated?

topaz breach
#

If you're pushing to dev you should get logs, so if they aren't being sent down for schema evaluation that's something for us to fix

devout meteor
#

I feely pretty certain that an undefined schema value would get blocked at the type level, as I'm not doing anything weird, no as, etc.

topaz breach
#

misspelling a validator could cause this (v.object({a}) where a is undefined) but yeah agree, should get a type error

devout meteor
#

I'm not even doing references for objects, it's all defined inline.

#

I've checked the diff since my last successful deploy, very limited changes to objects, and they're all inline using first class validators by direct reference

#

Is v.object() used by defineTable() to validate the whole table definition by chance?

#

That doesn't actually change my diagnosis as my top level fields are also all by direct reference, but wanted to check

topaz breach
#

if you can share the diff we might spot it, sorry for the lack of logs here. Removing one table or field at a time might get you there but sounds like you've been at this for a while.

#

Feel free to dm

devout meteor
#

Removing tables breaks types - if I turn off type checking will the schema eval run?

#

trying now

topaz breach
#

missed this, but yeah that makes sense

devout meteor
#

I get the error with an empty schema 😭

topaz breach
#

well that's interesting info

#

sorry you don't have a stack trace here, that would sure help!

devout meteor
#

I've now removed the schema file entirely, same error o_O

#

checking if I'm using v.object() in some obscure place

topaz breach
#

progress! delete everything else 💣

devout meteor
#

only used in the schema. yeah I'll keep deleting stuff

topaz breach
#

you think it's v.object because that's the only place we see v.json? from just the error it could be eg a fetch response being undefined

#

well not quite, that wouldn't run during schema push

devout meteor
#

The stack trace in the source points to v.object() specifically

#

It's running the object passed in to v.object() through Object.entries() and expecting the v in [k,v] to be an object

#

Deleting all of my convex code did indeed clear the error lol

#

I'll keep narrowing and let you know what I find

topaz breach
#

so far we know we need to make logs work here, and it sounds like this stack trace does not have as much info as we'd like (is it not showing the other stack frames?) so at least we have those to fix

#

plus whatever you find here

devout meteor
#

The trace includes a few frames, but doesn't go outside of v.object():

400 Bad Request: Error: Hit an error while pushing:
Uncaught TypeError: Cannot read properties of undefined (reading 'json')
    at <anonymous> (../../node_modules/convex/src/values/validator.ts:135:6)
    at map [as map] (<anonymous>)
    at object [as object] (../../node_modules/convex/src/values/validator.ts:131:12)
devout meteor
#

There may be other issues, but it seems likely to be down to this:

I have an oft-reused validator:

const authzValidator = v.object({
  users: v.id('users'),
  budgets: v.id('budgets'),
})

If I import this validator from another file and use it as an argument validator, I get the error.

If I use it inline, no error.

If I define it elsewhere in the same file and use it by reference, no error.

Only errors on import.

#

Furthermore:

  • I have one file per table for my db layer
  • some import this validator and some don't
  • of the ones that do, some can do so with no error, others cause the error
#

I've tried replacing the v.id() in the validator with v.string() in case it was some kind of weird table validation reference issue, but that made no difference.

#

Still digging.

devout meteor
#

@topaz breach I've gone ahead and used inline validators for every instance of this object, that solves it. Are nested objects validators not able to reference imported values? Wondering if I'm missing something.

#

Just realized it's the weekend, please ignore until you're on working hours!

devout meteor
#

Found a way - keeping the shared validator as a plain object and spreading it is the only way that doesn't produce errors. Each case below is exporting a validator and then importing and using that validator in function args.

// Fails in some cases, not sure why
export const fooBarValidator = v.object({
  bar: v.string(),
})
args: {
  foo: fooBarValidator,
}

// Fails at least some cases, maybe all - different error, "fooBarValidator is not a function" (it certainly is)
export const fooBarValidator = () => {
  return v.object({
    bar: v.string(),
  })
}
args: {
  foo: fooBarValidator()
}

// Works for some reason
export const fooBarValidator = {
  foo: v.object({
    bar: v.string(),
  }),
}
args: {
  ...fooBarValidator,
}
old ledge
#

I believe what you're running into is an import cycle. When TypeScript has a cycle, the objects might be undefined while it traverses the imports. Can you try putting the imported validator in a separate file imported in both places?

#

I ran into something like this in AI Town but I don't remember the specifics

devout meteor
#

Hmm it does sound like an import cycle, true - but it's already in a separate file, the authz file is shared by all of the other files

#

Will try though, that makes sense

devout meteor
#

@old ledge yep it was an import cycle, thanks for that

sick goblet
#

do you have an example of import cycle and how to identify them @devout meteor @old ledge