fal-studio-mobile-concurrency-errors

/home/avalon/.hermes/skills/.archive/software-development/fal-studio-mobile-concurrency-errors/SKILL.md · raw

fal-studio mobile concurrency + error handling

Use this for fal-studio-style apps where users compare many image/video models on mobile and need to launch multiple jobs without losing references.

When to use

Core patterns

1. Replace single-result state with a lightweight job queue

Do not use a single global result + generating pair if the user may launch another request before the first finishes.

Use frontend job state like: - jobQueue: [{ id, modelId, modelName, prompt, status, result, error, createdAt }] - activeJobId - derived activeJob - derived activeResult

Statuses: - queued - running - completed - failed

Flow: 1. Build FormData from the current prompt/model/uploads 2. Push a new job into jobQueue 3. Fire the request in an async closure without blocking model switching 4. On success: attach result, mark completed, refresh gallery/credits 5. On error: attach normalized error text, mark failed 6. Let the user tap job chips to inspect past/current jobs

This is enough for real multi-request concurrency in a standard Express + fal app without needing backend queues.

2. Preserve only compatible upload buckets across model switches

Users hate losing uploaded references when comparing nearby models.

Use upload buckets keyed by semantic purpose, not model-specific IDs: - generalReferences - firstFrame - lastFrame - storyboardReference

On model switch: 1. Compute old upload sections and new upload sections 2. Keep only keys that exist in the next model 3. Trim preserved files/previews to the new section's maxFiles 4. Clear only truly incompatible buckets

This works well for: - image edit → image edit - first-frame video → first-frame video - first/last-frame video → another first/last-frame video - storyboard-capable models with the same section key

3. Normalize fal errors before showing them to users

fal responses may include nested objects, arrays, or structured validation payloads. If you directly surface them, the UI may show [object Object] or object object object.

Implement a shared formatter that unwraps, in order: - error - detail - message - msg - reason - arrays of issues joined with - validation items with loc + type - final JSON.stringify fallback

Recommended mapping: - 401 → invalid key or missing access - 403 → likely safety/policy/provider restriction - 422 → invalid parameters or blocked request - 429 → rate limited - 5xx → provider-side failure

Use the same formatter on: - backend fal proxy route - frontend fetch wrapper / generation handler

4. Keep the generate bar visually stable on mobile

A bottom action bar that is directly position: fixed and also changes height/state can appear to jump.

Use: - outer fixed shell with safe-area padding - inner constrained bar with stable padding - gradient backdrop - enough .content bottom padding so content never collides with the CTA - touch-friendly min-height: 48px buttons on mobile

Recommended structure: - .generate-bar-shell → fixed full width + safe area + backdrop - .generate-bar → centered constrained content width

For fal-studio-like apps: - generation response can include previewUrl from fal - saved asset can be a local fallback URL or S3 URL - gallery should use the saved asset URL - result preview can prefer previewUrl

So keep helpers like: - getPrimaryResult(result) → prefer previewUrl, then saved URL - getAssetUrl(item) → prefer gallery-safe local/S3 URL - getResultKind(result) → trust explicit resultKind first

Verification checklist

After changes: 1. Launch one job, switch models, launch another — both must complete 2. Switch between two compatible reference-based models — uploads should remain 3. Trigger a provider rejection/moderation-ish failure — error should be readable, not object spam 4. Confirm generated assets still auto-save to gallery 5. Check mobile layout on a narrow viewport / iPhone screenshot 6. Build, restart PM2, verify dist/ timestamps, and spot-check other VPS apps

Good fit example

This pattern was used successfully on fal-studio when Alex wanted: - automatic gallery saves - multiple image/video jobs at once - preserved references while comparing similar models - cleaner mobile-first behavior - clearer Kling/fal error messages instead of object object object