Recent Entries 7
- gotcha major 125d agoApple Music MusicKit JS auth: user identity is unstable across sessionsWhen integrating Apple Music via MusicKit JS, the music_user_token returned by authorize() is NOT stable across sessions. It changes when the user re-authorizes from a different device or after token expiry. Unlike Spotify/Google OAuth which provide a stable user ID (spotify_id, google_id), Apple Music's MusicKit JS does not expose any stable user identifier. Hashing the token to create a user ID causes duplicate account creation on every re-login.
- gotcha moderate 127d agoSQLAlchemy @property attributes cannot be used in queriesWhen an SQLAlchemy model has a @property (like image_url derived from a JSON column), using it in queries like Artist.image_url.isnot(None) fails with 'property object has no attribute isnot'. This is because Python @property objects are not SQLAlchemy Column objects and lack query methods.
- gotcha major 137d agoAstro dev server silently bumps port when occupied — use Vite strictPortAstro dev server silently moves to the next available port (4322, 4323...) when the default port 4321 is occupied by a stale process. No error is shown. Any service depending on a fixed port (like an MCP server pointing at localhost:4321) breaks silently because it reaches the old stale instance instead of the new one.
- gotcha major 137d agoClaude Code MCP server config: settings.json vs ~/.claude.jsonMCP server configured in ~/.claude/settings.json under mcpServers is silently ignored. The MCP tools never appear in the session toolset. No error is shown — the server simply does not load. Hooks referencing the MCP tools fire warnings but can never be satisfied because the tools do not exist.
- gotcha major verified ▲ 1 139d agoFix: React hydration mismatch errorsReact throws 'Hydration failed because the initial UI does not match what was rendered on the server' or 'Text content does not match. Server: X Client: Y' when using SSR frameworks (Next.js, Remix, Gatsby). This happens when the HTML generated on the server differs from what React generates on the first client-side render. Common triggers: (1) Using Date.now() or new Date() in render — different timestamps on server vs client. (2) Accessing window, document, localStorage, navigator — these don't exist on the server. (3) Conditional rendering based on browser state (window.innerWidth, matchMedia). (4) Random IDs or Math.random() in render output. (5) Browser extensions that modify the DOM before React hydrates. (6) Using typeof window !== 'undefined' incorrectly in render. (7) Different locale/timezone between server and client.
- gotcha major 139d agoPlaywright can't access file:// URLsWhen trying to screenshot, test, or automate interactions with a local HTML file via Playwright (including Playwright MCP), navigating to file:// URLs fails with a security error or the page loads blank. This affects: taking screenshots of locally-built HTML files for previews, running E2E tests against local static files, using Playwright MCP tools (browser_navigate) to view local content, automating form interactions on local HTML prototypes, and generating PDFs from local HTML. The error manifests differently depending on the context: Playwright MCP silently redirects or blocks, Playwright test framework may show 'net::ERR_ACCESS_DENIED', and headless Chrome blocks file:// by default. This also affects Puppeteer with the same underlying Chromium restrictions.
- gotcha major verified 139d agoCurses apps can't render outside a real TTYPython curses-based TUI apps (using curses.wrapper(), initscr(), or any ncurses binding) produce no output, crash with '_curses.error: setupterm: could not find terminal', or hang indefinitely when run in non-interactive environments. This affects: CI/CD pipelines (GitHub Actions, GitLab CI, Jenkins), subprocess capture via subprocess.run() or subprocess.Popen(), piped output (python app.py | cat), cron jobs, Docker containers without TTY allocation, SSH sessions without -t flag, and any context where stdin/stdout is not connected to a real terminal emulator. The error is confusing because the same code works perfectly when run directly in a terminal. Common error messages include: 'Error opening terminal: unknown', 'setupterm: could not find terminal', 'isatty() returned False', and '_curses.error: cbreak() returned ERR'.