{"record":{"id":"045fb9c23f7e5f9c","repo":"paperclipai/paperclip","slug":"cli-auth-challenge-was-cancelled","errorCode":null,"errorMessage":"CLI auth challenge was cancelled.","messagePattern":"CLI auth challenge was cancelled\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cli/src/client/board-auth.ts","lineNumber":278,"sourceCode":"            authorization: `Bearer ${challenge.boardApiToken}`,\n          },\n        },\n      );\n      setStoredBoardCredential({\n        apiBase,\n        token: challenge.boardApiToken,\n        userId: me.userId ?? me.user?.id ?? null,\n        storePath: params.storePath,\n      });\n      return {\n        token: challenge.boardApiToken,\n        approvalUrl,\n        userId: me.userId ?? me.user?.id ?? null,\n      };\n    }\n\n    if (status.status === \"cancelled\") {\n      throw new Error(\"CLI auth challenge was cancelled.\");\n    }\n    if (status.status === \"expired\") {\n      throw new Error(\"CLI auth challenge expired before approval.\");\n    }\n\n    await sleep(pollMs);\n  }\n\n  throw new Error(\"CLI auth challenge expired before approval.\");\n}\n\nexport async function revokeStoredBoardCredential(params: {\n  apiBase: string;\n  token: string;\n}): Promise<void> {\n  const apiBase = normalizeApiBase(params.apiBase);\n  await requestJson<{ revoked: boolean }>(`${apiBase}/api/cli-auth/revoke-current`, {\n    method: \"POST\",","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/cli/src/client/board-auth.ts#L260-L296","documentation":"Startup warning at server/src/index.ts:443. The pid file check found no live postmaster, but the server could still connect with the embedded credentials (postgres://paperclip:paperclip@127.0.0.1:<configuredPort>/postgres) and `SELECT current_setting('data_directory', true)` returned a path that resolves to the same embedded dataDir. That means a PostgreSQL server is already serving this exact cluster without a usable postmaster.pid, so the server reuses it and never constructs or starts a new EmbeddedPostgres instance.","triggerScenarios":"postmaster.pid was deleted, truncated, or made unreadable while the embedded postgres kept running; the data dir is on a shared/volume mount where the pid file did not survive; an operator started postgres against this data dir manually/externally so this process never tracked its pid; a crashed supervisor removed the lock on restart.","commonSituations":"Partial cleanup of the data dir (rm of the lock file only) while the server was up; Docker/host volume mounts that exclude or lose the pid file; hand-run `postgres -D <dataDir>` during debugging; security tooling that deletes lock files.","solutions":["Confirm the reused server is really yours: `psql \"postgres://paperclip:paperclip@127.0.0.1:54329/postgres\" -c \"show data_directory;\"` and match it against the log message.","If the running server is stale or unwanted, stop it (`lsof -ti :54329 | xargs kill`) and restart the app so it owns the postgres lifecycle and regenerates postmaster.pid.","Never delete postmaster.pid of a running cluster as a 'fix'; plan one clean restart to restore normal lock-file tracking.","If the pid file lives on a mount that loses it, move the embedded data dir to stable local storage via database.embeddedPostgresDataDir."],"exampleFix":"# before: pid file removed while embedded postgres still running\nrm -f ~/.paperclip/embedded-postgres/postmaster.pid\n# server logs: \"...reachable without a pid file; reusing existing server on configured port 54329\"\n\n# after: let the app own the lifecycle — stop the stray postgres, then start cleanly\nkill $(lsof -ti :54329)\npnpm dev","handlingStrategy":"validation","validationCode":"import { resolve } from \"node:path\";\nimport postgres from \"postgres\";\n\n// Mirrors the server's probe: is the reachable server on this port OUR cluster?\nexport async function isExpectedEmbeddedServer(\n  adminUrl: string, // e.g. postgres://paperclip:paperclip@127.0.0.1:54329/postgres\n  expectedDataDir: string,\n): Promise<boolean> {\n  const sql = postgres(adminUrl, { connect_timeout: 2 });\n  try {\n    const [row] = await sql`select current_setting('data_directory', true) as d`;\n    return typeof row?.d === \"string\" && resolve(row.d) === resolve(expectedDataDir);\n  } catch {\n    return false;\n  } finally {\n    await sql.end();\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never delete postmaster.pid of a cluster that may be running; plan a clean restart instead.","Keep the embedded data dir on stable local storage (not a mount that drops lock files).","Avoid starting postgres manually against the embedded data dir; let the app own the lifecycle so the pid file stays authoritative."],"tags":["embedded-postgres","data-directory","pid-file","orphaned-process"],"backgroundTag":"process-already-running","analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}