fix: allow free-tier LLM in dev mode, improve error visibility

✅ merged · #3 · Archibald312/GordonOSS ← Archibald312/GordonOSS · opened 12d ago by Archibald312 · merged 12d ago by Archibald312 · self · +22-5 across 4 files · ↗ on GitHub

From the PR description

Summary

  • Free-tier LLM guard: the assertFreeTierAllowed guard was blocking all Gemini (free-tier) calls, including document-free ones like column prompt generation, because it required FREE_TIER_FIXTURE_ALLOWLIST even when no documents were involved. Fixed by returning early when documentFilenames is empty - no documents means no customer-data risk.
  • Tabular prompt error: the /tabular-review/prompt route had a bare catch {} that swallowed the real exception and always returned the generic "Failed to generate prompt from LLM" message. Now logs the error server-side and includes the actual message in the 502 response.
  • Upload error handling (documents.ts, projects.ts): AggregateError (which wraps multiple sub-errors) was being stringified as just the top-level message. Now expands all sub-errors and logs the full exception.

Root cause

The immediate trigger was that local dev only has GEMINI_API_KEY set, which routes to a free-tier Gemini model. The guard correctly blocked it, but the swallowed error made it impossible to diagnose without source-diving.

Test plan

  • Restart backend locally with ALLOW_FREE_TIER_LLM=true in .env
  • Open tabular review column editor and trigger auto-generate - should produce a prompt without error
  • Verify that document-backed LLM calls (tabular generation) still enforce the allowlist when documentFilenames is non-empty

Reviewer notes

ALLOW_FREE_TIER_LLM=true must be set in .env for local dev (not committed - add to .env.example if desired). Production should leave this unset or false.

🤖 Generated with Claude Code

Our analysis

Unblock free-tier LLM calls and surface real errors — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-3.md from inside the repo you want the changes in.

⬇ Download capture-pull-3.md