-
-
Notifications
You must be signed in to change notification settings - Fork 13
Description
Bug Description
When using custom types with @json attribute in ZenStack v3 beta with PostgreSQL, UPDATE operations fail with PostgreSQL error 22P02 (invalid_text_representation).
Environment
- ZenStack version: 3.0.0-beta.27
- Database: PostgreSQL (Supabase)
- ORM: @zenstackhq/orm with Kysely
Schema
type InlineButton {
id String
text String
callback_data String?
url String?
message String?
type String?
}
type BotButton {
id String
label String
action String
enabled Boolean
order_index Int
message String
inline_buttons InlineButton[]? // Nested custom type
}
model bot_settings {
id Int @id @default(autoincrement())
setting_key String @unique
menu_buttons BotButton[] @json // Array of custom type
@@schema("crm")
}Root Cause
Found in @zenstackhq/orm/dist/index.js:
SqliteCrudDialect (lines 1530-1531) - handles typeDefs correctly:
if (this.schema.typeDefs && type in this.schema.typeDefs) {
return JSON.stringify(value); // ✅ Custom types are serialized
}PostgresCrudDialect (lines 1285-1304) - missing typeDefs check:
transformPrimitive(value, type, forArrayField) {
if (Array.isArray(value)) {
return value.map((v) => this.transformPrimitive(v, type, false));
} else {
return match3(type)
.with("Json", () => {
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
return JSON.stringify(value);
} else {
return value; // ❌ Objects returned without serialization
}
})
.otherwise(() => value);
}
}When updating menu_buttons with nested inline_buttons, each BotButton object passes through the map function and ends up in the "Json" branch where objects are returned as-is (without JSON.stringify). Kysely then sends JavaScript objects to PostgreSQL, which expects a JSON string for JSONB columns.
Suggested Fix
Add typeDefs check to PostgresCrudDialect.transformPrimitive():
transformPrimitive(value, type, forArrayField) {
if (value === void 0) return value;
// Add this check (same as SqliteCrudDialect):
if (this.schema.typeDefs && type in this.schema.typeDefs) {
return JSON.stringify(value);
}
// ... rest of existing code
}Reproduction
- Create a model with nested custom @JSON types (type containing array of another type)
- Try to update the field with nested data
- PostgreSQL throws error 22P02
Workaround
Currently using raw SQL to bypass the issue, but this loses RLS/access control benefits of ZenStack.