run-posthog

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
PostHog is Django + Vite + Celery + plugin-server, backed by Postgres, ClickHouse, Kafka, Redis, and Temporal in Docker, fronted by an Envoy-style proxy at
http://localhost:8010
. The dev stack runs in detached mode under
phrocs
so the running processes are inspectable from this session via the
phrocs
MCP server. Browser MCP servers (
chrome-devtools-mcp
,
playwright
) drive the UI; nothing about this skill ships its own driver.
For
/run
: get the app reachable so the user can drive it. Success =
http://localhost:8010
serves and the core units are
ready
. Do not chase crashed migration units, do not seed data unless asked.
For
/verify
: build (Vite HMR handles this automatically for frontend; backend changes need no build), run the same launch as
/run
, then drive the live app via a browser MCP to observe the change. The observation is the verification — tests and type checks don't substitute. For frontend/UI changes, the deep version of this workflow is the repo-local
qa-frontend
skill in local mode: scenario design from the diff, reproducibility retries, and annotated evidence.
All paths below are relative to the repo root.
PostHog 基于 Django + Vite + Celery + plugin-server 构建,底层依赖Docker中的Postgres、ClickHouse、Kafka、Redis和Temporal,前端通过位于
http://localhost:8010
的Envoy风格代理提供访问。开发栈在
phrocs
下以分离模式运行,因此可以通过
phrocs
MCP服务器在当前会话中查看运行中的进程。浏览器MCP服务器(
chrome-devtools-mcp
、
playwright
)用于驱动UI;本技能不自带任何驱动程序。
对于
/run
:使应用可访问,以便用户能够操作它。成功标准 =
http://localhost:8010
可正常访问且核心单元处于
ready
状态。无需排查崩溃的迁移单元,除非明确要求,否则不要植入数据。
对于
/verify
:构建(前端由Vite HMR自动处理;后端变更无需构建),执行与
/run
相同的启动流程,然后通过浏览器MCP驱动实时应用以观察变更。观察结果即为验证依据——测试和类型检查不能替代。对于前端/UI变更,该工作流的深度版本是仓库本地的
qa-frontend
技能(本地模式):基于diff设计场景、可复现性重试,以及带注释的证据。
以下所有路径均相对于仓库根目录。

Prerequisites

前置条件

  • flox 1.12+ provisions the toolchain —
    curl -L https://downloads.flox.dev/by-env/stable/install.sh | sudo bash
  • Docker — OrbStack preferred on macOS (
    brew install --cask orbstack
    )
  • 1Password CLI (optional) —
    brew install 1password-cli
    , only if
    .env.local
    contains
    op://
    refs
  • flox 1.12及以上版本用于提供工具链——
    curl -L https://downloads.flox.dev/by-env/stable/install.sh | sudo bash
  • Docker — macOS上推荐使用OrbStack(
    brew install --cask orbstack
    )
  • 1Password CLI(可选)——
    brew install 1password-cli
    ,仅当
    .env.local
    包含
    op://
    引用时需要

Launch

启动

For a normal developer stack, use the saved interactive setup:
bash
hogli dev:setup          # first time only — interactive wizard picks which workers to run
hogli up -d -y           # start the stack detached under phrocs
hogli services:ready -y  # wait for Docker services (Postgres, CH, Kafka, Redis)
hogli wait -y            # broad all-process signal; confirm with the checks below
hogli doctor             # optional: stale migrations, zombie phrocs, disk pressure
For agent-managed QA, use the normal background stack unless the user asks to tune services. On a devbox, prefer
hogli devbox:start --start-app
for a new/stopped box; if it is already running without the app, start PostHog inside it:
bash
hogli devbox:exec -- bash -lc 'cd ~/posthog && ./bin/hogli up -d -y'
Use
hogli dev:intents
,
hogli dev:explain <intent>
, and
hogli dev:list-units <intent>
only to understand route-specific dependencies; custom generated configs are not the default QA startup path.
First boot is 60-90s while Django imports and Vite warms. Stop with
hogli down -y
(leaves Docker services running for fast restart).
对于常规开发栈,使用预设的交互式设置:
bash
hogli dev:setup          # 首次执行——交互式向导选择要运行的worker
hogli up -d -y           # 在phrocs下以分离模式启动栈
hogli services:ready -y  # 等待Docker服务就绪(Postgres、CH、Kafka、Redis)
hogli wait -y            # 广义的全进程信号;通过以下检查确认
hogli doctor             # 可选:检查过时的迁移、僵尸phrocs进程、磁盘压力
对于Agent管理的QA,除非用户要求调整服务,否则使用常规后台栈。在devbox上,对于新的/已停止的盒子,优先使用
hogli devbox:start --start-app
;如果它已经在运行但没有启动应用,则在其中启动PostHog:
bash
hogli devbox:exec -- bash -lc 'cd ~/posthog && ./bin/hogli up -d -y'
仅在需要理解特定路由依赖时使用
hogli dev:intents
、
hogli dev:explain <intent>
和
hogli dev:list-units <intent>
;自定义生成的配置不是默认的QA启动路径。
首次启动需要60-90秒,用于Django导入和Vite预热。使用
hogli down -y
停止(保留Docker服务运行以实现快速重启)。

Is the stack ready?

栈是否已就绪?

There are two readiness bars. Don't conflate them.
Ready for
/run
— the app is reachable and you can drive it:
bash
curl -sf http://localhost:8010/_health                                                         # 200
curl -sf -o /dev/null -w '%{http_code}' http://localhost:8010/                                 # 200 or 302
curl -sS http://localhost:8010/api/projects/@current | grep -q '"code":"not_authenticated"'   # API + DB reachable
For UI QA,
backend
and
frontend
are hard gates; add only units the route needs, such as
mcp
,
feature-flags
,
nodejs
,
capture
, or
ingestion
. Stop here. Do not chase crashed
migrate-*
units when only
/run
was asked
— the stack is usable for launch, screenshot, and most UI scenes (home, login, settings, feature flags) regardless of migration state.
Ready for
/verify
of HogQL-backed scenes
(insights, dashboards, web analytics) and for
POST /api/setup_test/...
:
  • Also requires
    mcp__phrocs__get_process_status process="migrate-clickhouse"
    to show
    status:"done" exit_code:0
    . If it's
    crashed
    , see the gotcha below.
phrocs MCP tools — for either bar:
  • mcp__phrocs__get_process_status
    (no args) — all units, with
    ready
    ,
    exit_code
    , memory, CPU.
  • mcp__phrocs__get_process_status process="frontend"
    — single unit.
  • mcp__phrocs__get_process_logs process="backend"
    — tail recent stdout/stderr.
  • mcp__phrocs__toggle_process process="<unit>"
    — restart one unit. Auto-mode blocks this on shared stacks (treated as restart-of-shared-infra). If blocked, ask the user to approve, or run
    phrocs stop && hogli up -d
    for a full clean restart.
有两个就绪标准,请勿混淆。
/run
就绪标准
——应用可访问且可操作:
bash
curl -sf http://localhost:8010/_health                                                         # 200
curl -sf -o /dev/null -w '%{http_code}' http://localhost:8010/                                 # 200 或 302
curl -sS http://localhost:8010/api/projects/@current | grep -q '"code":"not_authenticated"'   # API + 数据库可达
对于UI QA,
backend
和
frontend
是硬性门槛;仅添加路由所需的单元,例如
mcp
、
feature-flags
、
nodejs
、
capture
或
ingestion
。到此为止。当仅要求执行
/run
时,无需排查崩溃的
migrate-*
单元
——无论迁移状态如何,该栈都可用于启动、截图和大多数UI场景(首页、登录、设置、功能开关)。
适用于HogQL支撑场景(洞察、仪表盘、网页分析)和
POST /api/setup_test/...
的
/verify
就绪标准
:
  • 还要求
    mcp__phrocs__get_process_status process="migrate-clickhouse"
    返回
    status:"done" exit_code:0
    。如果状态为
    crashed
    ,请参阅下方的避坑指南。
phrocs MCP工具——适用于两种就绪标准:
  • mcp__phrocs__get_process_status
    (无参数)——查看所有单元,包含
    ready
    、
    exit_code
    、内存、CPU信息。
  • mcp__phrocs__get_process_status process="frontend"
    ——查看单个单元。
  • mcp__phrocs__get_process_logs process="backend"
    ——查看最近的标准输出/错误日志尾部。
  • mcp__phrocs__toggle_process process="<unit>"
    ——重启单个单元。自动模式下会在共享栈上阻止此操作(被视为重启共享基础设施)。如果被阻止,请请求用户批准,或运行
    phrocs stop && hogli up -d
    进行完整的干净重启。

Drive the UI for /verify

为/verify驱动UI

Every empty PostHog scene looks broken because no events exist. To verify a UI change, you need a workspace with realistic data. The canonical path is the same one the Playwright suite uses:
POST /api/setup_test/organization_with_team/
. Gated on
DEBUG=True | E2E_TESTING | CI | TEST
, all of which local dev satisfies via
DEBUG=True
. Implementation:
posthog/api/playwright_setup.py
+
posthog/test/playwright_setup_functions.py:create_organization_with_team
— 3 clusters via
HedgeboxMatrix
, ~5-10s end to end. Reference call site:
playwright/utils/playwright-setup.ts:251
.
Avoid
hogli dev:demo-data
for /run and /verify — it calls
generate_demo_data
with
n_clusters=500
(default at
posthog/management/commands/generate_demo_data.py:59
) and takes 5-30 minutes. It exists for humans who want a big realistic dataset to play with; it's the wrong tool for automated launch-and-screenshot.
The full browser-MCP recipe:
  1. new_page
    http://localhost:8010/login
    .
  2. evaluate_script
    the workspace bootstrap. Per-call email so reruns don't collide; password fixed at
    12345678
    ; response gives back the team_id and a personal API key.
    js
    const r = await fetch('/api/setup_test/organization_with_team/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ data: { skip_onboarding: true } }),
    })
    const { result } = await r.json()
    // result: { user_email, team_id, personal_api_key, organization_id, ... }
    return result
  3. evaluate_script
    the in-page login. Runs in the page context so Django's CSRF middleware sees the right cookies (
    playwright/utils/playwright-setup.ts:282-291
    ).
    js
    const r = await fetch('/api/login/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: workspace.user_email, password: '12345678' }),
    })
    return r.status // 200 = logged in; 403 = you're not in-page; 400 = workspace setup didn't actually create the user
  4. navigate_page
    to
    http://localhost:8010/project/{team_id}{scene-path}
    .
  5. wait_for
    text or a
    [data-attr]
    element. PostHog attaches
    data-attr
    to virtually every rendered element; use it as the "page hydrated" signal.
    networkidle
    and
    load
    never settle because PostHog.js and Vite HMR keep polling.
  6. take_screenshot
    . The accessibility snapshot from
    wait_for
    is also enough on its own for most "is this element present?" verifications — no pixel comparison needed.
For API-only calls (creating fixtures, hitting endpoints without a browser), use the
personal_api_key
from the setup_test response as
Authorization: Bearer <key>
— no login dance.
For deeper interaction (clicking, filling forms, inspecting console), the same MCP toolkit (
chrome-devtools-mcp:*
/
playwright:*
) covers it. No project-specific wrapper needed.
由于没有事件数据,空的PostHog场景看起来会像损坏了一样。要验证UI变更,你需要一个包含真实数据的工作空间。标准方法与Playwright测试套件使用的相同:
POST /api/setup_test/organization_with_team/
。该接口受
DEBUG=True | E2E_TESTING | CI | TEST
条件限制,本地开发环境通过
DEBUG=True
满足所有条件。实现位置:
posthog/api/playwright_setup.py
+
posthog/test/playwright_setup_functions.py:create_organization_with_team
——通过
HedgeboxMatrix
创建3个集群,端到端耗时约5-10秒。参考调用点:
playwright/utils/playwright-setup.ts:251
。
在/run和/verify中避免使用
hogli dev:demo-data
——它会调用
generate_demo_data
并设置
n_clusters=500
(默认值见
posthog/management/commands/generate_demo_data.py:59
),耗时5-30分钟。该命令是为想要体验大型真实数据集的人员设计的;不适合自动化启动和截图场景。
完整的browser-MCP操作流程:
  1. 使用
    new_page
    访问
    http://localhost:8010/login
    。
  2. 使用
    evaluate_script
    执行工作空间初始化。每次调用使用不同的邮箱以避免重复运行冲突;密码固定为
    12345678
    ;响应会返回team_id和个人API密钥。
    js
    const r = await fetch('/api/setup_test/organization_with_team/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ data: { skip_onboarding: true } }),
    })
    const { result } = await r.json()
    // result: { user_email, team_id, personal_api_key, organization_id, ... }
    return result
  3. 使用
    evaluate_script
    执行页内登录。在页面上下文中运行,以便Django的CSRF中间件能识别正确的Cookie(
    playwright/utils/playwright-setup.ts:282-291
    )。
    js
    const r = await fetch('/api/login/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: workspace.user_email, password: '12345678' }),
    })
    return r.status // 200 = 已登录;403 = 不在页内上下文;400 = 工作空间未成功创建用户
  4. 使用
    navigate_page
    跳转到
    http://localhost:8010/project/{team_id}{scene-path}
    。
  5. 使用
    wait_for
    等待文本或
    [data-attr]
    元素出现。PostHog几乎为每个渲染的元素都添加了
    data-attr
    ;可将其作为“页面已hydration”的信号。
    networkidle
    和
    load
    事件永远不会稳定,因为PostHog.js和Vite HMR会持续轮询。
  6. 执行
    take_screenshot
    截图。对于大多数“该元素是否存在?”的验证,
    wait_for
    返回的可访问性快照本身就足够了——无需像素对比。
对于纯API调用(创建测试夹具、无需浏览器访问端点),使用setup_test响应中的
personal_api_key
作为
Authorization: Bearer <key>
——无需登录流程。
对于更深度的交互(点击、填写表单、检查控制台),相同的MCP工具包(
chrome-devtools-mcp:*
/
playwright:*
)即可覆盖。无需项目特定的封装。

For /verify: diff → URL mapping

/verify指南:diff到URL的映射

The frontend uses kea-router. The mapping rule:
Edited pathScene URL (under
/project/{team_id}/
)
frontend/src/scenes/<name>/**
usually
/<name>
(e.g.
insights/
→
/insights
)
frontend/src/scenes/activity/**
/activity/explore
(and other
ActivityTab
s)
frontend/src/scenes/data-management/**
/data-management/<sub>
frontend/src/scenes/settings/**
/settings/<section>
frontend/src/scenes/authentication/**
/login
,
/signup
,
/preflight
(un-scoped)
products/<name>/frontend/**
per the
urls:
block in
products/<name>/manifest.tsx
frontend/src/layout/**
renders everywhere; verify on any scene
frontend/src/lib/components/<X>.tsx
grep usages, screenshot the scene that mounts it
Canonical sources to grep when the path isn't obvious:
  • frontend/src/scenes/urls.ts
    — top-level URL helpers (
    urls.insights()
    ,
    urls.dashboard(...)
    , etc.).
  • frontend/src/scenes/scenes.ts
    — scene-to-route registry.
  • products/<name>/manifest.tsx
    — per-product routes.
前端使用kea-router。映射规则如下:
编辑路径场景URL(位于
/project/{team_id}/
下)
frontend/src/scenes/<name>/**
通常为
/<name>
(例如
insights/
→
/insights
)
frontend/src/scenes/activity/**
/activity/explore
(以及其他
ActivityTab
)
frontend/src/scenes/data-management/**
/data-management/<sub>
frontend/src/scenes/settings/**
/settings/<section>
frontend/src/scenes/authentication/**
/login
、
/signup
、
/preflight
(无项目前缀)
products/<name>/frontend/**
参见
products/<name>/manifest.tsx
中的
urls:
块定义
frontend/src/layout/**
全局渲染;可在任意场景验证
frontend/src/lib/components/<X>.tsx
grep使用位置,对挂载该组件的场景截图
当路径不明确时,可在以下标准文件中grep查找:
  • frontend/src/scenes/urls.ts
    ——顶层URL辅助函数(
    urls.insights()
    、
    urls.dashboard(...)
    等)。
  • frontend/src/scenes/scenes.ts
    ——场景到路由的注册表。
  • products/<name>/manifest.tsx
    ——各产品的路由。

Gotchas

避坑指南

  • migrate-clickhouse
    and
    migrate-persons-db
    often crash on a cold
    hogli up -d
    due to a startup race.
    They start in parallel with
    migrate-postgres
    , and if Postgres isn't ready yet they crash. This is the hard prereq for
    POST /api/setup_test/...
    and for HogQL-backed scenes (insights, dashboards, web analytics) — but not for
    /run
    . Don't fix it unless the task needs HogQL/
    setup_test
    . When you do need to fix it, the canonical sequence is: wait for
    migrate-postgres
    to show
    status:"done"
    via
    mcp__phrocs__get_process_status
    , then restart the crashed migrations.
    mcp__phrocs__toggle_process
    is the surgical tool but auto-mode blocks it on shared stacks — fall back to
    phrocs stop && hogli up -d
    which re-runs everything in order, or run
    python manage.py migrate_clickhouse
    directly (you'll need
    set -a; source .env.services; set +a
    first so
    CLICKHOUSE_DATABASE=posthog
    , otherwise it targets
    default
    ). If neither works (corrupted CH replica state in ZooKeeper from a partial run),
    hogli dev:reset
    is the only path — it wipes Docker volumes, destructive.
  • hogli wait
    is a coarse all-process signal.
    Confirm with process-specific phrocs status, the
    curl
    probes, and the target route before deciding the stack is unusable.
  • Vite serves on
    :8234
    , not the URL you browse.
    You browse
    http://localhost:8010
    (the Envoy-style proxy). The proxy reverse-proxies Vite for
    /static/*
    and Django for everything else. Hitting
    :8234/
    directly returns 404 because Vite has no index route at the dev-server root.
  • Worktrees share Docker containers but compete for ports. All worktrees on the same machine resolve to the same
    posthog-clickhouse-1
    /
    posthog-db-1
    containers, so DB state is global. But ports 8000/8010/8234 can only be held by one worktree at a time — kill the granian/vite/phrocs of the other worktree before
    hogli up -d
    here.
  • CSP warnings and 401s in the browser console are normal pre-auth. The preflight/login page tries to fetch
    /api/projects/@current
    ,
    /api/users/@me/
    , and PostHog.js remote config — all 401 until you sign up. WASM/CSP "Report Only" warnings come from the dev CSP.
  • Direct
    curl -X POST /api/login/
    returns 403 (CSRF).
    Session login must run in-page via
    browser_evaluate
    so cookies and CSRF tokens flow. For non-browser API calls, use the
    personal_api_key
    from the
    setup_test
    response as
    Authorization: Bearer <key>
    — no CSRF on token auth.
  • .env.local
    may use 1Password refs.
    Without
    op
    installed, refs become literal strings (e.g.
    OPENAI_API_KEY=op://...
    ) and downstream services fail with cryptic auth errors. Install
    op
    or replace with literals.
  • 冷启动
    hogli up -d
    时,
    migrate-clickhouse
    和
    migrate-persons-db
    经常因启动竞争而崩溃。
    它们与
    migrate-postgres
    并行启动,如果Postgres尚未就绪就会崩溃。这是
    POST /api/setup_test/...
    和HogQL支撑场景(洞察、仪表盘、网页分析)的硬性前置条件——但不是
    /run
    的前置条件。除非任务需要HogQL/
    setup_test
    ,否则无需修复。当确实需要修复时,标准流程是:通过
    mcp__phrocs__get_process_status
    等待
    migrate-postgres
    显示
    status:"done"
    ,然后重启崩溃的迁移任务。
    mcp__phrocs__toggle_process
    是精准工具,但自动模式下会在共享栈上阻止此操作——可回退到
    phrocs stop && hogli up -d
    按顺序重新运行所有内容,或直接运行
    python manage.py migrate_clickhouse
    (需要先执行
    set -a; source .env.services; set +a
    以设置
    CLICKHOUSE_DATABASE=posthog
    ,否则会指向
    default
    数据库)。如果两种方法都无效(由于部分运行导致ZooKeeper中的CH副本状态损坏),
    hogli dev:reset
    是唯一的解决办法——它会清除Docker卷,具有破坏性。
  • hogli wait
    是一个粗粒度的全进程信号。
    在判定栈不可用之前,请结合特定进程的phrocs状态、
    curl
    探测结果和目标路由进行确认。
  • Vite在
    :8234
    端口提供服务,而不是你浏览的URL。
    你访问的是
    http://localhost:8010
    (Envoy风格代理)。代理将
    /static/*
    的请求反向代理到Vite,其他所有请求反向代理到Django。直接访问
    :8234/
    会返回404,因为Vite在开发服务器根目录没有索引路由。
  • 工作树共享Docker容器但会竞争端口。 同一机器上的所有工作树都会解析到相同的
    posthog-clickhouse-1
    /
    posthog-db-1
    容器,因此数据库状态是全局的。但8000/8010/8234端口同一时间只能被一个工作树占用——在此处执行
    hogli up -d
    之前,请先终止其他工作树的granian/vite/phrocs进程。
  • 身份验证前,浏览器控制台中的CSP警告和401错误是正常的。 预检查/登录页面会尝试获取
    /api/projects/@current
    、
    /api/users/@me/
    和PostHog.js远程配置——在你注册之前,这些请求都会返回401。WASM/CSP的“仅报告”警告来自开发环境的CSP配置。
  • 直接执行
    curl -X POST /api/login/
    会返回403(CSRF错误)。
    会话登录必须通过
    browser_evaluate
    在页内执行,以便Cookie和CSRF令牌正常传递。对于非浏览器API调用,使用
    setup_test
    响应中的
    personal_api_key
    作为
    Authorization: Bearer <key>
    ——令牌认证不存在CSRF问题。
  • .env.local
    可能使用1Password引用。
    如果未安装
    op
    ,引用会变成字面字符串(例如
    OPENAI_API_KEY=op://...
    ),导致下游服务出现难以理解的认证错误。请安装
    op
    或替换为字面量值。

Troubleshooting

故障排查

  • hogli up -d
    exits with
    Another instance of bin/start is already running
    — previous run still active or crashed without cleanup.
    mcp__phrocs__get_process_status
    shows what's there; if nothing's running,
    rm bin/start.lock
    and retry.
  • docker info
    fails with
    dial unix /Users/<you>/.orbstack/run/docker.sock: ... no such file
    — OrbStack is stopped.
    open -a OrbStack
    .
  • /api/projects/@current
    returns 500 instead of 401
    — Postgres or ClickHouse unreachable.
    docker ps | grep posthog-
    and look for unhealthy containers;
    hogli services:ready
    waits for all of them.
  • POST /api/login/
    returns 400
    invalid_credentials
    — you're logging in as a user the
    setup_test
    workspace didn't actually create (CH crash usually). Check the response of the setup_test call; if it 500'd, fix CH first (see the
    migrate-clickhouse
    gotcha).
  • POST /api/setup_test/organization_with_team/
    returns 404
    —
    DEBUG
    ,
    E2E_TESTING
    ,
    CI
    , and
    TEST
    are all false. Local dev has
    DEBUG=True
    by default; if it's not set,
    .env.local
    is missing or
    DJANGO_SETTINGS_MODULE
    points at a prod-like settings module.
  • POST /api/setup_test/organization_with_team/
    returns 500
    Table posthog.person does not exist
    —
    migrate-clickhouse
    crashed during boot. See the gotcha above.
  • In-page
    fetch('/api/login/')
    returns 403
    — you're calling it from outside the page context (e.g.
    page.request.post
    rather than
    page.evaluate
    ). Use
    evaluate_script
    /
    browser_evaluate
    so the call originates in-page.
  • hogli up -d
    退出并提示
    Another instance of bin/start is already running
    —— 之前的运行仍在活动中,或崩溃后未清理。
    mcp__phrocs__get_process_status
    可显示当前运行的内容;如果没有任何进程在运行,执行
    rm bin/start.lock
    后重试。
  • docker info
    失败并提示
    dial unix /Users/<you>/.orbstack/run/docker.sock: ... no such file
    —— OrbStack已停止。执行
    open -a OrbStack
    启动。
  • /api/projects/@current
    返回500而不是401
    —— Postgres或ClickHouse不可达。执行
    docker ps | grep posthog-
    查看是否有不健康的容器;
    hogli services:ready
    会等待所有容器就绪。
  • POST /api/login/
    返回400
    invalid_credentials
    —— 你尝试登录的用户实际上并未被
    setup_test
    工作空间创建(通常是因为CH崩溃)。检查setup_test调用的响应;如果返回500,请先修复CH(参见
    migrate-clickhouse
    避坑指南)。
  • POST /api/setup_test/organization_with_team/
    返回404
    ——
    DEBUG
    、
    E2E_TESTING
    、
    CI
    和
    TEST
    均为false。本地开发环境默认
    DEBUG=True
    ;如果未设置,可能是
    .env.local
    缺失,或
    DJANGO_SETTINGS_MODULE
    指向了类生产环境的配置模块。
  • POST /api/setup_test/organization_with_team/
    返回500
    Table posthog.person does not exist
    —— 启动过程中
    migrate-clickhouse
    崩溃。参见上方的避坑指南。
  • 页内
    fetch('/api/login/')
    返回403
    —— 你是在页面上下文之外调用的(例如使用
    page.request.post
    而不是
    page.evaluate
    )。请使用
    evaluate_script
    /
    browser_evaluate
    ,确保调用源自页内。