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

Next.js创建Thread时出现TypeError: Cannot redefine property: $$id错误求助

Next.js开发Threads克隆项目时创建帖子抛出500错误求助

提交帖子时触发500错误,报错日志如下:

- error node_modules/next/dist/build/webpack/loaders/next-flight-loader/action-proxy.js (37:11) @ defineProperties
- error TypeError: Cannot redefine property: $$id
    at Function.defineProperties (<anonymous>)
    at eval (./lib/actions/thread.actions.ts:43:81)
    at (actionBrowser)/./lib/actions/thread.actions.ts (/Users/danielrubio/Desktop/threads/.next/server/app/(root)/create-thread/page.js:3366:1)
    at Function.__webpack_require__ (/Users/danielrubio/Desktop/threads/.next/server/webpack-runtime.js:33:42)
null

注:报错指向thread.actions.ts第43行,但该文件实际只有37行


相关代码

thread.actions.ts 代码

'use server'

import User from "../models/user.model";
import Thread from "../models/thread.model";
import { connectToDB } from "../mongoose";
import { revalidatePath } from "next/cache";


interface Params {
  text: string,
  author: string,
  communityId: string | null,
  path: string,
}

export async function createThread({text, author, communityId, path} :Params) {
  try {
    connectToDB();

    const createdThread = await Thread.create({
      text,
      author,
      community: null,
    })
  
    await User.findByIdAndUpdate(author, {
      $push: { threads: createdThread._id }
    })
  
    revalidatePath(path);
  } catch(error: any) {
    throw new Error(`Failed to create thread: ${error.message}`);
  }
 
}

export default createThread;

Thread模型代码

import mongoose from 'mongoose';

const threadSchema = new mongoose.Schema({
  text: { type: String, required: true },
  author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    required: true
  },
  community: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Community'
  },
  createdAt: {
    type: Date,
    default: Date.now
  },
  parentId: {
    type: String
  },
  children: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Thread'
    }
  ]
  
})

const Thread = mongoose.models.Thread || mongoose.model('Thread', threadSchema);

export default Thread;

表单组件代码

'use client'

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod';
import { usePathname, useRouter } from 'next/navigation';
import { Button } from '../ui/button';
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form"
import { Textarea } from "@/components/ui/textarea"

import { ThreadValidation } from '@/lib/validations/thread';
import createThread from '@/lib/actions/thread.actions';

interface Props {
  userId: string;
}

function PostThread({ userId }: Props ) {
  const router = useRouter();
  const pathname = usePathname();

  const form = useForm({
    resolver: zodResolver(ThreadValidation), 
    defaultValues: {
      threads: '',
      accountId: userId,
    }
  })
  
  const onSubmit = async (values: z.infer<typeof ThreadValidation>) => {
    await createThread({
      text: values.thread,
      author: userId,
      communityId: null,
      path: pathname

    })

    router.push('/')
  }

  return(
    <Form {...form}>
      <form
        className='flex flex-col justify-start gap-10'
        onSubmit={form.handleSubmit(onSubmit)}
      >
  
        <FormField
          control={form.control}
          name='thread'
          render={({ field }) => (
            <FormItem className='flex w-full flex-col gap-3'>
              <FormLabel className='text-base-semibold text-light-2'>
                Content
              </FormLabel>
              <FormControl className='no-focus border border-dark-4 bg-dark-3 text-light-1'>
                <Textarea
                  rows={15}
                  {...field}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
    
        <Button type='submit' className='bg-primary-500'>
          Post Thread
        </Button>
      </form>
    </Form>
  )
  
}

export default PostThread;

排查方向及解决方法

  1. 解决Mongoose文档序列化问题
    Server Action对返回/处理的对象序列化有严格要求,Mongoose文档包含内部不可序列化属性会触发错误。修改createThread中的创建逻辑,只提取需要的ID:

    // 替换原创建线程的代码
    const threadDoc = await Thread.create({
      text,
      author,
      community: null,
    });
    // 直接用文档的_id更新用户
    await User.findByIdAndUpdate(author, {
      $push: { threads: threadDoc._id }
    });
    

    或者用lean()获取普通JS对象:

    const createdThread = await Thread.create({
      text,
      author,
      community: null,
    }).lean();
    
  2. 清理Server Action导出冲突
    你同时使用了命名导出和默认导出,可能导致Next.js处理混乱。删除默认导出:

    // 删掉这一行
    // export default createThread;
    

    然后在表单组件中改为导入命名导出:

    import { createThread } from '@/lib/actions/thread.actions';
    
  3. 清除Next.js缓存并重启服务
    缓存残留可能导致旧代码执行,执行以下命令后重启开发服务器:

    rm -rf .next/
    npm run dev
    
  4. 检查参数与校验规则匹配
    表单默认值写的是threads: '',但提交时用的是values.thread,确保ThreadValidation中的字段名是thread,避免参数传递错误。

  5. 适配Next.js版本
    该错误多与App Router的Server Action处理逻辑相关,尝试升级Next.js到最新稳定版,或者切换到教程使用的特定版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 00:47:32