Skip to content
flypod

Troubleshooting

Match a flypod error code or HTTP status to its cause and fix. Covers auth failures, stale links, expired sites, abuse rejections, size caps, rate limits, and rendering.

Each section below names one symptom — an error string or an HTTP status — and gives its cause and its fix. Sections are self-contained and can be read in any order.

The three most common: unauthorized means the CLI has no credential that site accepts; 410 Gone means an anonymous deploy passed its 14-day expiry (within minutes it is deleted, and then its address returns 404); 403 on deploy means the upload was rejected by content screening.

unauthorized on flypod update, versions or rollback

The same applies to plain flypod in a folder that already has a site, since that run is an update.

Why: you are not logged in, the saved manage_token is wrong or missing, the site has been claimed (an owned site accepts only its owner's session, so its old manage_token stops working), the site belongs to another account, or the site no longer exists. The server answers the same way for all of these, so the error says what this machine sent and the fix follows from it:

  • the folder's stored token was refused: the site was kept by an account, or it no longer exists. If you are signed in, flypod already retried as your account.
  • an account was refused: the site is not on the account you are signed in to.
  • nothing was sent: an owned site needs flypod login; a site this machine has no record of was made on another machine or install.

Fix: log in with the account that owns the site, or run flypod --new to start a separate new site from this folder. A temporary site can only be changed from the machine that made it, unless you pass its token explicitly.

flypod login
# or
flypod update ./dist --token <manage_token>

If you still get unauthorized while logged in, the site belongs to a different account (or was deleted), so you cannot manage it. Exit code 3.

The credential you sent was not accepted (token_rejected)

Why: a deploy carried a bearer token — usually FLYPOD_TOKEN or a saved login — that the server did not accept: it is expired, revoked, or not a session token. flypod never falls back to an anonymous deploy when a credential was sent, so nothing was deployed.

Fix: run flypod login again or set a valid FLYPOD_TOKEN. To deploy anonymously on purpose, unset FLYPOD_TOKEN. Exit code 3.

Not signed in (not_signed_in)

Why: the command is account-only (flypod list, flypod claim, flypod comments …) and there is no saved session or FLYPOD_TOKEN.

Fix: flypod login, or set FLYPOD_TOKEN. Exit code 3.

Sign-in needs a browser (interactive_login_required)

Why: flypod login --json was run where nobody can open a browser (an agent or CI), or a coding agent ran plain flypod login with no terminal. The JSON carries verification_uri_complete, user_code and device_code.

Fix: have a person open the URL and confirm the user_code. Nothing else is needed: once they have, the next flypod command of any kind (a deploy, flypod list) finishes signing in and keeps every site on the machine. To finish at once, run flypod login --device-code <device_code> --json, which waits up to 25 seconds; still unconfirmed, it fails with authorization_pending (exit 4: run it again, or carry on and let the next command finish it). login_denied, login_expired and login_timeout mean start again with flypod login --json. login_expired is also the answer to a code that was already used (if an earlier run printed "ok":true, you are signed in) or to the user_code passed in place of the device_code. Codes expire after ten minutes.

Reading an error

Every command fails the same way. The reason is on a line starting with ✗, and the next step is underneath it:

  ✗ No flypod site is linked to this folder.
    Run `flypod` here to create one, or pass --site <id>.

With --json the same failure is one line of JSON on stdout, with a stable code to branch on and the same text in error and fix. The exit code follows the code: 0 success, 1 a runtime error you can act on, 2 usage (the command line needs changing), 3 auth (not signed in, or the credential was refused), 4 retryable (rate limit, server error, network, a login still pending). Every code is listed in Errors and exit codes; the sections below cover the ones people hit most.

No flypod site is linked to this folder (no_site)

Why: this folder has no link to a site. The message and the JSON reason say which case it is:

  • never_linked: nothing was deployed from this folder on this machine.
  • expired: this folder's temporary site reached its expiry, and the CLI dropped the link.
  • gone: the server reported the site gone (site_gone), and the CLI dropped the link.
  • other_folder: a folder above or below this one is the linked one (you deployed from the repo root and are now inside dist/, or the other way round).

Fix: for other_folder, run the command from the linked folder or pass the --site <id> the fix names. Otherwise deploy a fresh site; after an expiry, flypod login keeps the new one for good.

flypod

flypod update succeeded but flypod versions didn't grow

Why: expected. A version id is the hash of the deploy's content, so re-running flypod update with byte-identical files resolves to the version that already exists. Nothing is re-stored and no new version row is created — but the upload still happens and the CLI still reports the version as live, so the command looks identical either way. There is no "nothing changed" message.

Fix: nothing is broken. This is what makes flypod update safe to call on every iteration of an agent loop or a CI job: an unchanged run cannot pile up versions. If you want to skip the upload itself, gate the call on your own change detection.

flypod rollback refuses (no_such_version)

Why: there is only one version, the live version is already the oldest one, or the version id you passed matches nothing. Versions that are not live are deleted once they are 7 days old, so an older version may simply no longer exist.

Fix: run flypod versions to see what is left, then flypod rollback <version_id>; or deploy a new version first.

flypod update ./dist

Visiting a site returns 410 Gone (or 404 "not serving a site")

Why: an anonymous deploy expired. Anonymous sites have a 14-day TTL (24 hours if the content screen flagged the deploy as suspicious). The site answers 410 from the moment it expires; the garbage collector deletes it within minutes, after which the address answers 404 and a browser sees a page saying the preview has most likely expired.

Fix: redeploy. To avoid expiry next time, deploy while logged in. To save sites you already deployed anonymously, run flypod login — it auto-claims every anonymous site this CLI remembers. See /docs/concepts/ephemerality.

A site returns 451

Why: an operator disabled the site for abuse.

Fix: nothing self-serve. The site was taken down deliberately.

A deploy is rejected with 403 (blocked or challenge_required)

Why: blocked means the abuse guard flagged the content (for example a credential or login form whose action posts to another domain). challenge_required means the server wants a human challenge for an anonymous deploy. Updates are rescanned too, and an update the guard would challenge is refused as blocked.

Fix: read the fix in the error: it says what was seen. A sign-in page deploys when the password goes only in the body of a POST to your own backend, or through your auth provider's SDK, never in a URL or to a chat or webhook address. Deploying the same files again gets the same answer; if the refusal is wrong, tell us at flypod.dev/abuse. For challenge_required, run flypod login and deploy again: signed-in deploys skip the challenge.

A 401 or 403 whose body is not flypod's JSON came from a proxy or firewall between you and the server, not from flypod; the CLI reports it as network.

Upload rejected as too large (too_large)

Why: the deploy exceeds the size cap on flypod.dev: 200 files, 10 MB of files, and a 12 MB upload per deploy. The CLI checks this before uploading and names the largest files.

Fix: trim the build (drop source maps, large media, or unused assets), or list what the site does not need in a .flypodignore, so it fits under the cap. When a few files are the difference, the error's fix names them as .flypodignore lines, and says which folder's .flypodignore to put them in.

Too many requests (rate_limited)

Why: flypod.dev allows 10 deploys per minute from one IP address. Agent loops and parallel CI jobs behind one NAT hit it first.

Fix: wait and retry the same command; the JSON carries retry_after_s when the server sends one. Exit code 4 means retryable, as do server_error and network.

No build output folder found (no_build_dir)

Why: auto-detection looks for an index.html inside one of dist/, build/, out/, .output/public, .vercel/output/static, public/, or _site/ (in that order), or in the one app folder inside one of them, and found none. The current folder deploys as it is only when it has an index.html and no package.json (or other project file): a project root is never deployed by guesswork. Usually the project has not been built yet, or a Next.js app is not set to export static files.

Fix: run the command in the error's fix. It names the build command for the project's package manager and the folder the framework writes (Run `npm run build`, then `flypod ./dist`.), or the folder here that already has an index.html. Or pass the directory explicitly.

flypod ./path

Markdown didn't render as a docs site

Why: rendering only happens when there is no index.html at the deploy root. If an index.html is present, flypod serves the files as-is and skips rendering.

Fix: remove the root index.html (or deploy a directory without one) to get the rendered docs site. See /docs/guides/render-markdown.

On this page