更新PostgreSQL枚举值后NestJS订单更新功能异常
基于NestJS+TypeORM+PostgreSQL(Vercel托管)的应用中,订单实体status列使用枚举类型,原有值为pending、vendor、dispatched。手动更新数据库的order_status_enum枚举,新增delivered和returned后,尝试将订单状态改为这两个新值时,触发400错误,提示Invalud order status type(实际应为Invalid拼写错误)。
错误日志
exception: BadRequestException: Bad Request Exception 0|cwc-nest-server | at ValidationPipe.exceptionFactory (/home/ubuntu/servers/cwc-nest/node_modules/@nestjs/common/pipes/validation.pipe.js:99:20) 0|cwc-nest-server | at ValidationPipe.transform (/home/ubuntu/servers/cwc-nest/node_modules/@nestjs/common/pipes/validation.pipe.js:72:30) 0|cwc-nest-server | at processTicksAndRejections (node:internal/process/task_queues:93:5) 0|cwc-nest-server | at resolveParamValue (/home/ubuntu/servers/cwc-nest/node_modules/@nestjs/core/router/router-execution-context.js:147:23) 0|cwc-nest-server | at async Promise.all (index 0) 0|cwc-nest-server | at pipesFn (/home/ubuntu/servers/cwc-nest/node_modules/@nestjs/core/router/router-execution-context.js:150:13) 0|cwc-nest-server | at /home/ubuntu/servers/cwc-nest/node_modules/@nestjs/core/router/router-execution-context.js:37:30 { 0|cwc-nest-server | response: { 0|cwc-nest-server | statusCode: 400, 0|cwc-nest-server | message: [ 'Invalud order status type' ], 0|cwc-nest-server | error: 'Bad Request' 0|cwc-nest-server | }, 0|cwc-nest-server | status: 400, 0|cwc-nest-server | options: {} 0|cwc-nest-server | } 0|cwc-nest-server | request method: PUT request url/api/v1/orders/1 request method: PUT request url/api/v1/orders/1 {"statusCode":400,"timestamp":"2023-12-27T20:47:37.094Z","path":"/api/v1/orders/1","method":"PUT","errorName":"BadRequestException","message":"Bad Request Exception"}
数据库状态
Vercel上的PostgreSQL数据库中,order_status_enum枚举已包含新增的delivered和returned值,完整枚举列表为:pending、vendor、dispatched、delivered、returned。
相关代码
订单实体(Order)
@Entity('orders') export class Order extends BaseEntity { @PrimaryGeneratedColumn('increment') id: number; @Column({ length: 500, }) description: string; @Column({ nullable: true, }) quantity: number; @Column({ nullable: false, }) amount: number; @ManyToOne(() => Customer, (customer) => customer.orders) customer: Customer; @OneToMany(() => OrderProduct, (orderProduct) => orderProduct.order, { cascade: true, }) @JoinTable() products: Array<OrderProduct>; @Column({ nullable: false, type: 'enum', enum: OrderStatus, default: OrderStatus.PENDING, }) status: OrderStatus; @CreateDateColumn() createdAt: Date; }
更新前的OrderStatus枚举
export enum OrderStatus { PENDING = 'pending', VENDOR = 'vendor', DISPATCHED = 'dispatched' }
更新后的OrderStatus枚举
export enum OrderStatus { PENDING = 'pending', VENDOR = 'vendor', DELIVERED = 'delivered', DISPATCHED = 'dispatched', RETURNED = 'returned', }
UpdateOrderDTO
export class UpdateOrderDto { @IsString() @IsNotEmpty() @Length(5, 400) @IsOptional() public description: string; @IsNotEmpty() @IsNumber() @IsPositive() @IsOptional() public amount: number; @IsNotEmpty() @IsNumber() @IsOptional() public customerId: number; @IsNotEmpty() @IsArray() @IsOptional() @ValidateNested({ each: true }) @Type(() => OrderProductDto) products: OrderProductDto[]; @IsOptional() @IsEnum(OrderStatus, { message: 'Invalud order status type' }) public status: OrderStatus; }
该错误是class-validator的DTO校验失败,与数据库枚举无关,按以下顺序排查:
确认枚举引用正确性
检查UpdateOrderDto中导入的OrderStatus是否为更新后的版本,避免引用旧文件或错误的枚举导出。清除应用缓存并重启
- 开发环境:重启NestJS服务,确保新枚举代码被编译加载,避免热重载缓存旧代码。
- 生产环境:重新构建项目后部署,彻底替换旧的编译产物。
校验请求参数与枚举值匹配
确保请求体中传递的status值为全小写字符串(与枚举的字符串值完全一致,比如delivered而非Delivered),@IsEnum会严格匹配大小写。修正错误拼写
DTO中@IsEnum的提示消息里Invalud是拼写错误,改为Invalid order status type,避免后续排查混淆。验证TypeORM枚举同步(可选)
如果之前启用了synchronize: true,确认TypeORM能正确识别枚举变更,但由于已手动更新数据库,此步骤非必需,重点仍在应用层校验。
内容的提问来源于stack exchange,提问作者Fahad Subzwari

