Applied formatting to 1487+ files using pnpm format:write - TypeScript/JavaScript files - Svelte components - Astro pages - JSON configs - Markdown docs 13 files still need manual review (Astro JSX comments)
5.1 KiB
🐛 Bug Analysis: process-jobs Function
Date: 2025-10-09 Status: ✅ ROOT CAUSE IDENTIFIED
Problem
The process-jobs Edge Function fails with error:
{"success":false,"error":"Cannot read properties of undefined (reading 'substring')"}
Investigation Steps
Step 1: Test without imports
Created process-jobs-test with minimal code (no imports).
Result: ✅ Works perfectly
- Environment variables present
- Supabase client initializes
claim_next_job()RPC works
Step 2: Test WITH process-generation import
Added import { processGeneration } from '../process-generation/index.ts';
Result: ❌ Same error returns
Root Cause
The process-generation/index.ts file has a Deno.serve() handler at the end!
// Line 522-565 of process-generation/index.ts
Deno.serve(async (req: Request) => {
// Handler code...
});
Why this causes the error:
- Edge Functions can only have ONE
Deno.serve()call - When
process-jobsimportsprocess-generation/index.ts, it executes the file - This tries to call
Deno.serve()a second time - This causes a runtime error in Deno/Edge Functions environment
- The error happens during import, before any of our code runs
Solution
Option A: Extract to Shared Module (RECOMMENDED)
Create a new file process-generation/lib.ts that contains ONLY the processGeneration() function and helper functions (NO Deno.serve).
Structure:
supabase/functions/
├── process-generation/
│ ├── lib.ts ← Pure functions, NO Deno.serve
│ └── index.ts ← Edge Function handler, imports from lib.ts
├── process-jobs/
│ └── index.ts ← Imports from ../process-generation/lib.ts
Benefits:
- Clean separation
- Reusable code
- Each function has its own Deno.serve
Option B: Inline Code (FALLBACK)
Copy-paste the processGeneration() function directly into process-jobs/index.ts.
Benefits:
- Simple
- No import issues
- All code in one place
Drawbacks:
- Code duplication
- Harder to maintain
- Larger file
Option C: Remove Deno.serve from process-generation
Remove the Deno.serve handler from process-generation/index.ts entirely if it's not needed as a standalone function.
Drawbacks:
- Can't call process-generation directly for testing
- Loses standalone functionality
Recommended Implementation
Go with Option A: Extract to Shared Module
Step 1: Create process-generation/lib.ts
Extract these from index.ts:
- All interfaces (ModelConfig, GenerationParams, GenerationResult)
- All helper functions (gcd, simplifyAspectRatio, convertImageToBase64, buildModelInput, determineOutputFormat)
- Main function:
processGeneration()
Step 2: Update process-generation/index.ts
import 'jsr:@supabase/functions-js/edge-runtime.d.ts';
import { processGeneration } from './lib.ts';
Deno.serve(async (req: Request) => {
// Handler code...
const result = await processGeneration(params, replicateApiToken);
// Return response...
});
Step 3: Update process-jobs/index.ts
import { processGeneration } from '../process-generation/lib.ts';
// Now this works without conflict!
Step 4: Deploy
npx supabase functions deploy process-generation --project-ref mjuvnnjxwfwlmxjsgkqu
npx supabase functions deploy process-jobs --project-ref mjuvnnjxwfwlmxjsgkqu
Testing Plan
-
Test process-generation standalone:
curl -X POST https://.../ /functions/v1/process-generation \ -H 'Authorization: Bearer SERVICE_ROLE_KEY' \ -d '{"prompt": "test", "model_id": "flux-schnell", ...}' -
Test process-jobs:
curl -X POST https://.../functions/v1/process-jobs \ -H 'Authorization: Bearer SERVICE_ROLE_KEY' -
Test with real job:
SELECT enqueue_job( 'generate-image', '{"generation_id": "test-id", "prompt": "test", ...}'::jsonb, 0 );Then trigger process-jobs and verify job is processed.
Timeline
- 14:00 UTC - Bug discovered during deployment
- 14:15 UTC - Initial debugging started
- 14:30 UTC - Created minimal test function (works)
- 14:35 UTC - Added import (fails - reproduced bug)
- 14:40 UTC - ROOT CAUSE IDENTIFIED: Deno.serve() conflict
- 14:45 UTC - Solution designed
- Next: Implement fix
Lessons Learned
- Edge Functions can only have ONE Deno.serve() per file
- When importing files, ALL code in that file executes (including Deno.serve)
- Shared code should be in separate files without Deno.serve()
- Always test imports early to catch these issues
Impact
Before Fix:
- ❌ process-jobs fails immediately
- ❌ Cron job fails every minute
- ❌ Jobs stay pending forever
- ✅ Other functions work fine
After Fix:
- ✅ process-jobs works
- ✅ Cron job processes queue
- ✅ End-to-end flow complete
- ✅ System fully operational
Fixed By: Claude Code Status: Ready to implement ETA: 15 minutes