Symptom, then the fix. Run commands in the attendee's Ubuntu: ask their Claude session to run them, or open an Ubuntu
terminal. On a Mac, ask their Claude session or use Terminal; their app folders are in the projects folder they chose
(~/appdev by default; cat ~/.workshop/apps-dir shows it). Background is in INSTRUCTOR-NOTES.md, and what the family social network app does
and does not include is in its section there.
- A compile is stuck, or compiling again (or saving the Plan) fails with
409andcompilation_active. A compile normally takes 30 to 45 seconds. The error names the Compilation, ascurrent.compilation.idor in the 409'sresponse.detail("Compilation<id>is already active..." or "Cancel active Compilation<id>..."). Run these in the app folder (or in its.firstdraft/designif the app was already compiled once):- Once CLI 0.8.2 is installed (
firstdraft --version;npm install --global @firstdraft.com/cli@latestupdates it):firstdraft compilation cancel <id>, then compile again. - CLI 0.8.1 has no cancel. Wait 3 minutes, then
firstdraft compilation status <id> --wait(it returns when the Compilation finishes, or after 10 minutes).succeeded:firstdraft compilation download <id> --output ..failedorcancelled: compile again. - Still
queuedorrunning: start a fresh Project in a new folder, or cancel it with the attendee's token.
- Once CLI 0.8.2 is installed (
- A compile ends with a 502, a timeout,
request_outcome_unknownorcompilation_status_unavailable. Do not compile again while it may still be running. Withcurrent.compilation.idin the error, wait a minute, then runfirstdraft compilation status <id> --waitand download it as above once it succeeds. With no ID, compiling once more is safe: while the first one is active, First Draft refuses with409 compilation_activeand names it (row above). If anything else keeps the Project blocked, start a fresh Project. analyzer_release_mismatch(foundation_plan.analysis.analyzer_release_mismatch) right after a First Draft deploy: the Plan was analyzed while the deploy was switching releases. Compile again once. Do not deploy First Draft during the workshop.- Many compiles fail at the same time. 30 compiles started within 5 seconds all succeeded after the 2026-10-03 capacity upgrade; 50 is untested. With more than 30 people, start compiles by table, about a minute apart.
- A native preview fails with
/up returned HTTP 403, orlog/bin-dev.logshowsBlocked hosts: ….trycloudflare.com. The web app was started without the tunnel's host. Stop it and start it asRAILS_DEVELOPMENT_HOSTS=.trycloudflare.com bin/dev </dev/null >log/bin-dev.log 2>&1(the attendee can typeRestart the web app.). - On a Mac, the app's first page shows
The asset 'application.css' was not found in the load path, or style changes stop showing up. The Mac has Homebrew'swatchman, which stalls the CSS watcher (tailwindlabs/tailwindcss#17246). In the app folder, runnpm run build:cssonce, then reload. If later style changes still don't show, restart the web app withWATCHMAN_SOCK=/dev/nullin front of its usual start command. <URL>/upfails withCould not resolve hostright aftercloudflaredprinted the address. A new quick tunnel can take up to 2 minutes to resolve. Wait and retry. Starting another tunnel does not help and counts against Cloudflare's limit on new tunnels (429 or error 1015).- Revyl says "Concurrency limit reached", or the helper says a preview session already exists. The last phone is
still shutting down. Wait 15 to 30 seconds, run
bin/<platform> preview revyl stopagain (or stop it on the Revyl dashboard under Sessions), then retry. Ignore the upgrade hint. - A photo upload fails with
KeyError: key not found: "CLOUDINARY_URL". On the laptop: in the app folder, runbash ~/.workshop/cloudinary.sh install ., then restart the web app. If it printsMISSING, the attendee runs/workshop-signinin a new session first (it redoes only what is missing). On the live app: the Render service was created without the key, so delete it (render services delete <service-id> --confirm) and create it again with the same Neon project. cloudinary.sh savekeeps printingINVALID. It wants three copies from the API Keys page, in this order: the copy button by API environment variable, the API Key, then the API Secret from the same row, shown with its eye button first (dots or stars are not the secret).
- After an attendee limits the length of a longer text, such as "Limit posts to 280 characters",
bin/cior GitHub CI fails atSchema: active_record_doctor: "the length validator on Post.caption enforces a maximum of 280 characters but there's no schema limit". The column istext, which has no limit. Ask Claude to add the attribute it names (Post.captionhere) toincorrect_length_validation'signore_attributesin.active_record_doctor.rb, with a one-line comment, as the app'sAGENTS.mdsays. The README no longer suggests this change.
- The first deploy fails with
function uuidv7() does not exist. The Neon database is PostgreSQL 17, a claimable database fromnpx get-dbor neon.new. Create a PostgreSQL 18 project (neonctl projects create --name <app> --region-id aws-us-east-2 --pg-version 18 --org-id <id> -o json, with the ID fromneonctl orgs list -o json), delete the Render service (render services delete <service-id> --confirm), and deploy again with the new project's direct connection string. The Render CLI cannot change a service's environment variables. - Render shows the app's free services as suspended. That workspace used up its 750 free instance hours for the month, and Render suspends every free web service in it. One workspace per app avoids this, which is why the deploy notes have the attendee create a Hobby workspace named after the app (dashboard workspace switcher, then New workspace) before its first deploy.
- Render's New workspace form shows Hobby as "Limit reached" and preselects Pro ($25/month). Render allows five Hobby workspaces per account. Do not choose Pro. Close the form and deploy into one of the attendee's existing workspaces, the one with the fewest free web services; the app then shares that workspace's free hours.
- Render cannot see the repository after the attendee created the app's workspace. A new workspace may need its own GitHub connection (not yet tested): open https://github.com/apps/render/installations/new, or the workspace's GitHub settings on the Render dashboard, and connect it.
- The live app is empty. Expected: sample data and demo logins are development-only. Attendees sign up there.
- The first CI run is red, or 20 or more Dependabot pull requests appear. Harmless; ignore them.
- A sign-up page (Revyl, Cloudinary) shows errors or a security check. The venue network may be blocking it: have the attendee use a phone hotspot.
- The sign-in skill has no Cloudinary step, or shows
[FAIL] cloudinary: helper not installed. The laptop was set up from an older zip. Download the zip again, open itsworkshop-kitfolder in a Local session, typecontinue(it redoes the handoff; give the same app name), then run/workshop-signinagain in a WSL session (on a Mac, a Local session). - An attendee may have old First Draft packages. In Ubuntu (on a Mac, Terminal),
firstdraft --versionshows the CLI (0.8.2 today) andnpm ls -g @firstdraft.com/claude-codeshows the plugin (0.8.7 today). If either is older, runnpm install --global @firstdraft.com/cli@latest @firstdraft.com/claude-code@latestthere, then start a new session. With a kit zip downloaded on 2026-10-05 or later, typingcontinuein a Local session in itsworkshop-kitfolder also works: setup sends old packages back to the install step (on a Mac,bash scripts/mac/setup.sh install-toolsfrom that folder does the same). Older zips do not check for updates.
- The setup's Terminal window says
Need sudo accessornot in the sudoers file. The attendee's macOS account is not an administrator. Someone with an administrator account must install Homebrew, or the attendee uses the Codespace guide. - The attendee closed the Terminal window before it said "You can close this window". Ask Claude to stop the
waiting step and run
bash scripts/mac/setup.sh statusagain; it reopens the window. [FAIL] xcode-clt: installed but clang does not run. Xcode is installed but its license was never accepted. In Terminal, the attendee runssudo xcodebuild -license acceptand types their password, then typescontinue.- A Mac attendee is stuck at the Terminal's password prompt. Typing a password in Terminal shows nothing at all, not even dots, so attendees think it's broken. Have them type their Mac login password anyway and press Return; after "Sorry, try again", they retype it. Their account must be an administrator.
[FAIL] postgres: server is version 1X, expected 18. Another PostgreSQL (Postgres.app, or another Homebrew version) holds port 5432. Stop it (quit Postgres.app, orbrew services stop postgresql@1X), thencontinue.- A new session cannot find
ruby,node,psqlorrender, or finds older ones. Claude Desktop was not restarted after setup: quit it with Cmd-Q and reopen it. If another version manager (asdf, rbenv, nvm) is listed after the workshop lines in~/.zshrc, its versions win; ask Claude to move the# Added by workshop setuplines to the end of~/.zshrcand~/.zprofile. git pushasks for a passphrase. The attendee already had an SSH key with a passphrase, which setup keeps. They type the passphrase in Terminal once (ssh-add --apple-use-keychain ~/.ssh/id_ed25519).- macOS asks whether Claude may access Downloads, Documents or Desktop. The kit or a file is there: click Allow.
- A Mac project is in a synced folder anyway (Dropbox, iCloud Drive, or Desktop or Documents with iCloud sync),
with git errors such as
bad objectorindex.lock, files ending in2or(conflicted copy), or a slow web app. Ask Claude to commit and push what works. Then, in the kit's setup folder, runbash scripts/mac/setup.sh folder ~/appdevandbash scripts/mac/setup.sh handoff <name>, open a Local session in~/appdev/<name>, and ask Claude to clone the app's GitHub repository there.
For a Project that a stuck compile blocks. It copies the Plan into a new Project in a new folder; replace APP with
the app folder's name. An app compiled before keeps its Plan under .firstdraft/design/.firstdraft/, so the first two
lines pick that copy when it exists:
PLAN=~/APP/.firstdraft/design/.firstdraft/foundation-plan.json &&
{ [ -f "$PLAN" ] || PLAN=~/APP/.firstdraft/foundation-plan.json; } &&
mkdir ~/APP-2 && cd ~/APP-2 &&
firstdraft plan init --name "Fresh Project" &&
cp "$PLAN" .firstdraft/ &&
firstdraft plan compileplan init only creates the new Project's ID; the copied Plan replaces its name. Then the attendee opens a new session
in /home/appdev/APP-2 (WSL, Ubuntu-24.04) and continues from README step 12. On a Mac, use the projects folder
(~/appdev by default) in place of ~ in the commands, and open a Local session in its APP-2.
For CLI 0.8.1. Run it where the stuck-compile commands run (the app folder, or its .firstdraft/design) after
replacing COMPILATION_ID. It reads the Project ID and the attendee's saved First Draft token from their files, sends
the token to First Draft only, and never prints it (-q ignores any ~/.curlrc, which could turn on verbose output):
P=$(python3 -c 'import json; print(json.load(open(".firstdraft/state.json"))["project_id"])') &&
T=$(python3 -c 'import json, os; print(json.load(open(os.path.expanduser("~/.config/firstdraft/credentials.json")))["origins"]["https://firstdraft.com"]["access_token"])') &&
printf 'Authorization: Bearer %s\n' "$T" | curl -q -sS -X POST -H @- \
"https://firstdraft.com/v1/projects/$P/compilations/COMPILATION_ID/cancel"A reply with "status":"cancelled" frees the Project: compile again. compilation_not_cancellable means it had
already finished: check it with firstdraft compilation status.