You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

签发JWT时遇「Expected 'payload' to be a plain object」错误求助

解决JWT生成错误:「Expected 'payload' to be a plain object」

问题场景

在Node.js+TypeScript+Hapi.js+Docker环境下,生成JWT用于访问其他路由时触发错误:Expected "payload" to be a plain object。

错误栈信息

apis_1      | Error: Expected "payload" to be a plain object.
apis_1      |     at validate (/lens-apis/node_modules/jsonwebtoken/sign.js:40:11)
apis_1      |     at validatePayload (/lens-apis/node_modules/jsonwebtoken/sign.js:62:10)
apis_1      |     at Object.module.exports [as sign] (/lens-apis/node_modules/jsonwebtoken/sign.js:114:7)
apis_1      |     at /lens-apis/dist/org/signup/signup.route.js:115:37
apis_1      |     at Generator.next (<anonymous>)
apis_1      |     at fulfilled (/lens-apis/dist/org/signup/signup.route.js:5:58)
apis_1      |     at processTicksAndRejections (internal/process/task_queues.js:95:5)

相关代码

JWT生成逻辑

if (!user) {
  return h.response({
    message: "User does not exist",
  });
} else if (!upassword) {
  return h.response({
    message: "Your Password is incorrect",
  });
} else {
  let token = jwt.sign(user, process.env.JWT_SECRET, {
    expiresIn: "1h",
  });
  if (!token) {
    console.log("token not found");
  }
  return h.response({
    message: "you have successfully logged in",
    token: `${token}`,
  });
}

导入代码

import { ServerRoute } from "@hapi/hapi";
import Joi, { options } from "joi";
import { ISignup, IsLogin } from "./signup.types";
import firebase from "firebase-admin";
import { User } from "../../user/user.model";
import { Org } from "../org.model";

解决方案

错误原因是user是SQL ORM的模型实例(而非纯JavaScript对象),jsonwebtoken的sign方法要求payload必须是无额外原型方法/元数据的普通键值对对象。以下是几种可行的解决方式:

1. 手动提取必要字段构建纯对象(推荐)

只将JWT需要的核心字段(如用户ID、邮箱)作为payload,既符合要求又减少token体积、提升安全性:

// 提取需要的字段
const tokenPayload = {
  userId: user.id,
  email: user.email,
  // 按需添加其他必要字段,避免传入整个模型实例
};

let token = jwt.sign(tokenPayload, process.env.JWT_SECRET, {
  expiresIn: "1h",
});

2. 使用ORM内置方法转换为纯对象

如果使用Sequelize等常见SQL ORM,可调用实例的内置方法转换:

// Sequelize 可用 toJSON()
let token = jwt.sign(user.toJSON(), process.env.JWT_SECRET, { expiresIn: "1h" });

// 或者 get({ plain: true })
let token = jwt.sign(user.get({ plain: true }), process.env.JWT_SECRET, { expiresIn: "1h" });

3. 通用序列化转换(兜底方案)

通过JSON序列化再反序列化,强制将实例转为纯对象(注意:可能丢失不可序列化的属性):

const plainUser = JSON.parse(JSON.stringify(user));
let token = jwt.sign(plainUser, process.env.JWT_SECRET, { expiresIn: "1h" });

内容的提问来源于stack exchange,提问作者mzee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 15:39:37