bookworm-smart-assistant/skills/debugger-expert/references/common-errors.md

10 KiB
Raw Blame History

常见错误速查与修复方案 (Common Errors Reference)

格式:错误信息 -> 常见原因 -> 修复命令/代码


一、CORS 错误

错误信息

Access to fetch at 'http://api.example.com' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present.

常见原因

  • 后端未配置 CORS 响应头
  • 预检请求 (OPTIONS) 未正确处理
  • 允许的 Origin 列表遗漏了前端地址
  • Nginx 反代层未透传 CORS 头

修复方案

Nginx 配置

server {
    location /api/ {
        # 处理预检请求
        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '$http_origin';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Max-Age' 86400;
            return 204;
        }
        add_header 'Access-Control-Allow-Origin' '$http_origin' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        proxy_pass http://backend:8000;
    }
}

Express 配置

import cors from 'cors';
app.use(cors({
  origin: ['http://localhost:3000', 'https://yourdomain.com'],
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
}));

FastAPI 配置

from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "https://yourdomain.com"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

二、React Hydration 错误

错误信息

Hydration failed because the initial UI does not match what was rendered on the server.

常见触发场景

  • 使用 Date.now()Math.random() 等在服务端和客户端产生不同值的表达式
  • 根据 window / localStorage 条件渲染内容
  • 嵌套了无效的 HTML 结构(如 <p> 内嵌 <div>
  • 浏览器扩展注入了额外的 DOM 节点

修复方案

// 方案1使用 useEffect 延迟客户端渲染
function ClientOnlyTime() {
  const [time, setTime] = useState<string>('');
  useEffect(() => {
    setTime(new Date().toLocaleString());
  }, []);
  return <span>{time || '--'}</span>;  // 服务端渲染占位符
}

// 方案2使用 suppressHydrationWarning
<time dateTime={dateString} suppressHydrationWarning>
  {formattedDate}
</time>

// 方案3使用 next/dynamic 禁用 SSR
import dynamic from 'next/dynamic';
const BrowserOnlyChart = dynamic(() => import('./Chart'), { ssr: false });

三、Next.js 常见错误

3.1 "use client" 边界错误

Error: You're importing a component that needs useState. It only works in a
Client Component but none of its parents are marked with "use client".

修复:在使用 React hooks 的组件文件顶部添加 "use client";

"use client";  // 必须是文件的第一行
import { useState } from 'react';
export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

3.2 Server/Client 组件混用

Error: Functions cannot be passed directly to Client Components unless you
explicitly expose it by marking it with "use server".

修复:不要将函数 prop 从 Server Component 传给 Client Component改用 Server Actions

// app/actions.ts
"use server";
export async function submitForm(data: FormData) {
  // 服务端逻辑
}

// app/page.tsx (Server Component)
import { submitForm } from './actions';
import ClientForm from './ClientForm';
export default function Page() {
  return <ClientForm action={submitForm} />;
}

3.3 Dynamic Import 问题

Error: Element type is invalid: expected a string or a class/function but got: undefined

修复:确认 dynamic import 的组件使用了 default export

// 确保组件使用 default export
const DynamicComponent = dynamic(() => import('./MyComponent'), {
  loading: () => <p>加载中...</p>,
  ssr: false,  // 如果组件依赖浏览器 API
});

四、Prisma/ORM 错误

4.1 Connection Pool Exhaustion

Error: Timed out fetching a new connection from the connection pool.

修复

// schema.prisma - 调整连接池
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// 连接字符串中设置池大小
// DATABASE_URL="postgresql://user:pass@host:5432/db?connection_limit=20&pool_timeout=10"
// 确保 Prisma Client 为单例
// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;

4.2 Migration Drift

Error: The current database is not managed by Prisma Migrate.

修复

# 重置迁移历史(开发环境)
npx prisma migrate reset

# 将现有数据库与 schema 对齐
npx prisma db pull          # 从数据库生成 schema
npx prisma migrate dev      # 生成新迁移

4.3 类型不匹配

Error: Argument of type 'string' is not assignable to parameter of type 'number'.

修复:运行 npx prisma generate 重新生成类型,确保 schema 和代码类型一致。


五、PostgreSQL 错误

5.1 连接超时

Error: connect ETIMEDOUT / Connection refused

排查步骤

# 检查 PostgreSQL 是否在运行
sudo systemctl status postgresql
# 或 Docker 环境
docker ps | grep postgres

# 检查监听端口
ss -tlnp | grep 5432

# 检查 pg_hba.conf 是否允许远程连接
# host  all  all  0.0.0.0/0  md5

# 检查 postgresql.conf
# listen_addresses = '*'

# 测试连接
psql -h localhost -U myuser -d mydb -c "SELECT 1;"

5.2 死锁检测

ERROR: deadlock detected
DETAIL: Process 1234 waits for ShareLock on transaction 5678;
blocked by process 9012.

排查与修复

-- 查看当前锁等待
SELECT pid, usename, query, state, wait_event_type, wait_event
FROM pg_stat_activity
WHERE state = 'active' AND wait_event IS NOT NULL;

-- 查看锁冲突
SELECT blocked.pid AS blocked_pid,
       blocking.pid AS blocking_pid,
       blocked.query AS blocked_query
FROM pg_catalog.pg_locks blocked
JOIN pg_catalog.pg_locks blocking
  ON blocking.locktype = blocked.locktype
  AND blocking.relation = blocked.relation
  AND blocking.pid != blocked.pid
WHERE NOT blocked.granted;

-- 终止阻塞进程(谨慎使用)
SELECT pg_terminate_backend(<blocking_pid>);

5.3 索引失效

常见原因对列使用了函数、隐式类型转换、LIKE '%前缀'

-- 错误:函数导致索引失效
SELECT * FROM users WHERE LOWER(email) = 'test@example.com';

-- 修复:创建表达式索引
CREATE INDEX idx_users_email_lower ON users (LOWER(email));

-- 检查查询是否使用了索引
EXPLAIN ANALYZE SELECT * FROM users WHERE LOWER(email) = 'test@example.com';

六、Docker 错误

6.1 端口冲突

Error: Bind for 0.0.0.0:3000 failed: port is already allocated

修复

# 查找占用端口的进程
# Linux/Mac
lsof -i :3000
# Windows
netstat -ano | findstr :3000

# 停止占用端口的容器
docker ps | grep 3000
docker stop <container_id>

# 或更换端口映射
docker run -p 3001:3000 myapp

6.2 权限问题

Error: EACCES: permission denied

修复

# Dockerfile 中设置正确的用户
RUN addgroup --system app && adduser --system --ingroup app app
RUN chown -R app:app /app
USER app

6.3 网络不通

Error: Could not resolve host / Connection refused between containers

修复

# docker-compose.yml - 确保服务在同一网络
services:
  app:
    networks:
      - backend
    depends_on:
      - db
  db:
    networks:
      - backend
networks:
  backend:
    driver: bridge

# 容器间使用服务名访问,不要使用 localhost
# DATABASE_URL=postgresql://user:pass@db:5432/mydb

6.4 构建缓存失效

# 强制重新构建(不使用缓存)
docker compose build --no-cache

# 清理悬空镜像和构建缓存
docker system prune -f
docker builder prune -f

# 优化 Dockerfile 层顺序以利用缓存
# 把不常变化的放前面(安装依赖),常变化的放后面(复制代码)

七、Git 错误

7.1 Merge Conflict

CONFLICT (content): Merge conflict in src/app.ts
Automatic merge failed; fix conflicts and then commit the result.

修复

# 查看冲突文件
git status

# 手动编辑冲突文件,选择保留的代码
# 删除 <<<<<<<, =======, >>>>>>> 标记

# 标记为已解决
git add src/app.ts
git commit -m "resolve merge conflict in app.ts"

# 或放弃合并
git merge --abort

7.2 Detached HEAD

You are in 'detached HEAD' state.

修复

# 查看当前位置
git log --oneline -5

# 创建新分支保存当前改动
git checkout -b my-fix-branch

# 或回到原来的分支
git checkout main

7.3 大文件推送失败

remote: error: File large-file.zip is 150.00 MB; this exceeds the 100 MB limit.

修复

# 从历史中移除大文件
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch large-file.zip' HEAD

# 使用 Git LFS 管理大文件
git lfs install
git lfs track "*.zip"
git add .gitattributes
git add large-file.zip
git commit -m "track large files with LFS"

# 添加 .gitignore 防止再次提交
echo "*.zip" >> .gitignore