[S] | unauthorized on docker pull (self-hosted) | Docker login in different context (sudo vs user) | docker login ghcr.io in the same context that runs the pull |
[S] | network declared as external, but could not be found | Incorrect nginx-proxy network name in secret | docker network ls | grep proxy and fix NGINX_NETWORK_NAME |
[S] | ERR_SSL_VERSION_OR_CIPHER_MISMATCH | DNS does not point to the server | dig domain +short should resolve to the server IP |
[S] | Deploy queued indefinitely | Self-hosted runner offline | systemctl status actions.runner.* on the server (host runner) OR docker ps | grep runner (containerized — see self-hosted-runner-docker.md §7 if in Restarting with 404 /actions/runner-registration) |
[S] | CD step emits yellow ::warning:: on every deploy ("ENOENT" or similar in a script that finished its real work first) | Script writes output path resolved upward from __dirname — exists in dev source tree, missing in container image (Dockerfile only copies packages/<self>/); continue-on-error: true masks indefinitely | cd-pipeline-pitfalls.md §5 — wrap the write in try/catch best-effort and emit the artifact via console.log so CD logs capture it |
[S] | Deploy blocked | Concurrency group with previous run | Wait or cancel previous run via gh run cancel |
[S] | --max-warnings 0 fails in ESLint | Pre-existing warnings | Fix warnings or use eslint-disable |
[B] | manifest unknown in service container | Discontinued Docker image | Switch to official image (e.g., postgres:17) |
[B] | Zod validation error on boot | Missing env vars in CI or in Generate .env | Compare src/env.ts with env: block of tests and printf in CD |
[B] | ZodError invalid_string | Secret URL missing https:// protocol | Check secret format |
[B] | Tests pass locally, fail in CI | Case-sensitivity in imports (Linux) | Fix file or import case |
[B] | FATAL ERROR: heap limit / Exit 134 | Jest OOM | node --max-old-space-size=4096 |
[B] | EADDRINUSE in tests | server.ts calls app.listen() in test | Guard NODE_ENV !== 'test' |
[B] | ERR_CONNECTION_REFUSED (nginx-proxy OK) | VIRTUAL_PORT not defined in compose | Add VIRTUAL_PORT: '${API_PORT}' |
[B] | tsc type errors (Prisma client) | --skipLibCheck missing | Add --skipLibCheck to tsc |
[F] | Blank page (SPA doesn't load) | Missing VITE_* or vite.config.ts absent | Check ARGs in Dockerfile and build-args in workflow |
[F] | VITE_API_URL = undefined in JS | VITE_* not passed as build-arg | Check build-args in docker/build-push-action |
[F] | 404 on React Router routes | nginx try_files not configured | try_files $uri $uri/ /index.html in nginx.conf |
[F] | Cannot access 'X' before initialization | treeshake.moduleSideEffects + circular chunks | Remove treeshake and manualChunks from vite.config.ts |
[F] | Container unhealthy (healthcheck fails) | Alpine resolves localhost as IPv6 | Use 127.0.0.1 in healthcheck |
[F] | Vitest collecting Playwright E2E tests | vitest.config.ts without e2e/ exclude | Add exclude: ['e2e/**'] |
[B] | npx biome check . fails on config files | Biome checks all files by default | Use files.includes in biome.jsonc to scope or fix the config files |
[B] | Biome 2.x config error (unknown key "ignore") | Biome 2.x removed ignore in favor of includes | Use files.includes instead of files.ignore in biome.jsonc |
[B] | Migration reports "No pending migrations" but app crashes with missing column | Stale Docker image cache on self-hosted runner (docker run does not pull if tag exists locally) | docker pull the image before docker run in the migration step |
[F] | Container nginx returns 403 | dist/ empty or not copied | Check npm run build and COPY --from=build in Dockerfile |
[S] | Missing script: "exec" ao rodar tsc/playwright/openapi-typescript em workspace | Sintaxe inválida npm run -w <ws> exec -- <cmd> (não existe script exec; exec é subcomando de npm, não script de package.json) | Substituir por npm exec -w <ws> -- <cmd> |
[S] | ESLint couldn't find an eslint.config.(js|mjs|cjs) file em workspace de monorepo | ESLint v9 removeu auto-detect de .eslintrc.*; flat config existe em outro workspace e não se propaga | Criar eslint.config.js por workspace que rode eslint. Pacotes Node-only: globals.node, sem eslint-plugin-react-hooks / react-refresh |
[S] | Cannot find package 'X' imported from /node_modules/<other-pkg> em monorepo | devDep tem subtree em versões antigas que conflita com a raiz → npm aninha em packages/<ws>/node_modules/X; outras deps hoisted não acham via Node ESM resolution | Trocar por dep com subtree compatível (ex.: jsdom→happy-dom), OU declarar a dep no package.json raiz para forçar hoist, OU overrides para dedup das transitive deps conflitantes |
[F] | Vitest pré-test fail (Cannot find package 'jsdom') ou TypeError: signal AbortSignal em msw v2 | jsdom@20 não hoista em monorepo (subtree pesado) + injeta AbortController próprio incompatível com undici nativo do Node usado pelo msw v2 | Trocar para happy-dom: npm i -D happy-dom -w <ws> e environment: 'happy-dom' em vitest.config.ts. Subtree leve hoista limpo + AbortController nativo |