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

Mercurius上下文内Prisma报Undefined错误求助

问题:Fastify + Mercurius 上下文传递Prisma为undefined

错误信息

{
  "type": "GraphQLError",
  "message": "Cannot read properties of undefined (reading 'user')",
  "stack": "TypeError: Cannot read properties of undefined (reading 'user')"
}

相关代码

上下文传递代码

import AltairFastify from "altair-fastify-plugin";
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import mercurius from "mercurius";
import mercuriusCodegen from "mercurius-codegen";
import { makeSchema } from "nexus";
import { schemaTypes } from "./graphql/index";
import path from "path";

const buildContext =
  (fastify: FastifyInstance) =>
  async (req: FastifyRequest, _reply: FastifyReply) => ({
    req,
    prisma: fastify.prisma,
  });

const schema = makeSchema({
  types: schemaTypes,
  outputs: {
    schema: `${__dirname}/generated/schema.graphql`,
    typegen: `${__dirname}/generated/typings.ts`,
  },
  contextType: {
    module: path.join(process.cwd(), "src", "graphql", "context.ts"),
    export: "Context",
  },
});

export async function initGraphql(app: FastifyInstance) {
  try {
    await app.register(mercurius, {
      schema,
      graphiql: false,
      ide: false,
      path: "/graphql",
      allowBatchedQueries: true,
      context: buildContext(app),
    });

    await app.register(AltairFastify, {
      path: "/altair",
      baseURL: "/altair/",
      endpointURL: "/graphql",
    });

    await mercuriusCodegen(app, {
      targetPath: `${__dirname}/generated/graphql.ts`,
    });
  } catch (err: unknown) {
    app.log.error(err);
  }
}

Prisma插件代码

import fp from "fastify-plugin";
import { PrismaClient } from "@prisma/client";

/**
 * Prisma plugin for Fastify.
 */
export default fp(async (fastify) => {
  // Initialize Prisma client
  const prisma = new PrismaClient();

  // Decorate Fastify with Prisma client instance
  fastify.decorate("prisma", prisma);

  // Add a hook to close the Prisma client when Fastify is shutting down
  fastify.addHook("onClose", async (instance) => {
    await prisma.$disconnect();
  });

  fastify.log.info("Prisma started...");
});

Nexus Resolver代码

export const UserMutation = mutationType({
  definition(t) {
    t.field("createUser", {
      type: UserType,
      args: {
        firstName: nonNull(stringArg()),
        lastName: nonNull(stringArg()),
        phoneNumber: nonNull(stringArg()),
        otp: nonNull(stringArg()),
      },
      resolve: async (_parent, args, { req, prisma }) => {
        console.log(prisma);
        const { jwt } = req.server;
        const user = await prisma.user.create({
          data: args,
          select: {
            id: true,
            // 更多字段
          },
        });
        const token = jwt.signToken(user.id);
        return { ...user, token };
      },
    });
  },
});

问题描述

Resolver中prisma始终为undefined,已确认Prisma插件内部实例化正常,直接在Resolver中实例化Prisma Client也能成功,但通过上下文传递失败,使用fastify-starter模板。


解决方案

1. 调整插件注册顺序(核心修复)

Fastify的装饰器仅在插件注册完成后生效,必须先注册Prisma插件,再初始化GraphQL。

在主入口文件(如app.ts)中确保顺序如下:

import fastify from "fastify";
import prismaPlugin from "./prisma-plugin";
import { initGraphql } from "./graphql/init";

const app = fastify();

// 第一步:注册Prisma插件
await app.register(prismaPlugin);

// 第二步:初始化GraphQL
await initGraphql(app);

await app.listen({ port: 3000 });

若先初始化GraphQL再注册Prisma插件,buildContext执行时fastify.prisma还未被装饰,会直接返回undefined。

2. 验证Context类型定义(可选)

确保src/graphql/context.ts中的Context接口包含prisma字段,避免类型不匹配:

import type { FastifyRequest } from "fastify";
import type { PrismaClient } from "@prisma/client";

export interface Context {
  req: FastifyRequest;
  prisma: PrismaClient;
}

3. 确认插件作用域配置

你的Prisma插件已使用fastify-plugin包装,这会将装饰器暴露到全局作用域,确保Mercurius能访问到fastify.prisma,这部分代码无需修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:55:31