AI-coded apps

    Why is my Replit Expo deploy stuck on the View Log login page?

    A Replit Shell window with the eas-cli printing a View Log link, a browser tab showing the Expo login page in a redirect loop, and the Replit Secrets pane open in a second panel with EXPO_TOKEN highlighted as the unblock

    You ran eas build or eas submit from your Replit Shell, the CLI printed a View Log link with a sign in URL, and the page never moves past the login prompt. A refresh sends you back to the same screen, the deploy stays paused, and the Shell waits for an authenticated session that never lands.

    Short answer

    Inside a Replit container the eas-cli prints a one-time login URL and waits for a browser session to redirect back to the process. The redirect rarely lands cleanly, and any session it does establish dies when the workspace recycles. The clean fix is a personal access token from the Expo dashboard, stored as EXPO_TOKEN in Replit Secrets, per Expo's CI authentication guidance. The CLI then skips the browser handshake entirely.

    What you should know

    • EXPO_TOKEN overrides the interactive login. When the env var is set, the eas-cli authenticates with the token and never opens the View Log URL as a sign-in step.
    • Replit Secrets are injected at runtime. The token in the Secrets pane reaches the Shell process for free; no .env file or dotenv package is required.
    • The View Log link is not a Replit feature. It is the eas-cli's hosted log viewer, gated by your Expo session, which is why an unauthenticated browser stalls there.
    • The editor Shell and the Deployment Shell are separate. A token set only in editor Secrets will not appear in a published deployment without being copied to the Publishing pane.
    • Personal access tokens have full account scope. Treat them like a password, rotate them after a project ends, and prefer a robot user for shared CI work.

    When the eas-cli runs from your Replit Shell, it tries to authenticate with Expo's servers in three steps: it prints an authorization URL, opens a local callback port on the container, and waits for the browser to redirect a session token back. According to Expo's documentation on programmatic access, this browser flow is the default interactive path when no token is configured.

    Inside Replit the flow breaks at the callback step. The browser opens on your laptop and the callback port lives inside a container with no public address visible to that browser. The CLI treats the hosted page as the entry point and prints a View Log link so you can follow the in-flight session. The link reads as if it is the login itself, which is why most developers click it, see the Expo sign-in page, and assume the deploy needs another login.

    The page does need a session, but it is the running CLI process that needs it, not the browser tab. Logging into Expo from that page authenticates your dashboard session, not the CLI process. The deploy keeps waiting until the CLI's callback port hears back, which never happens.

    Replit Discourse threads about Expo auth in Replit projects describe the same loop: a sign-in URL that returns to itself, a Shell process that prints a fresh URL each retry, and no progress in the build queue.

    How do you set EXPO_TOKEN as a Replit Secret correctly?

    Three steps move the deploy off the login screen.

    First, create a personal access token. From the Expo dashboard, open Account Settings, then Access Tokens, then Create. Copy the token immediately because Expo only shows the value once. Per Expo's access token guidance, the token grants account-wide actions and should be treated like a password.

    Second, open Replit Secrets in the editor sidebar. Click New Secret, enter the key EXPO_TOKEN, paste the token as the value, and save. Replit injects Secrets as environment variables into the Shell process at startup, so a Shell that was already running before you saved the Secret will not see the new value.

    Third, kill the stalled process. From the same Shell, run kill 1 to recycle the workspace, then start a fresh run with npx eas build --platform ios or eas submit. The CLI reads EXPO_TOKEN from the environment and authenticates directly with Expo's servers. The View Log link no longer appears as a login wall because no browser handshake is required.

    For a deployed Replit app that calls eas submit from a published web service or scheduled job, add EXPO_TOKEN separately in the Publishing pane. Editor Secrets and Publishing Secrets are stored in different stores, and a missing copy in the Publishing pane is a frequent reason the same loop reappears after a successful local test.

    What is the difference between eas login, EXPO_TOKEN, and the browser auth flow?

    The three authentication paths are not interchangeable. Each one targets a different runtime and a different lifetime.

    MethodHow it authenticatesWhere it worksWhen it breaks in Replit
    eas loginInteractive prompt for email and passwordLocal terminal with a TTYThe Replit Shell is partly non-interactive; a long password paste can be truncated and the prompt may not redisplay after a SIGINT
    Browser callbackCLI prints a URL, the browser redirects a session token to a local callback portA local machine where the browser and CLI sit on the same networkThe Replit container's callback port is not reachable from your laptop's browser, so the View Log page hangs on the sign-in step
    EXPO_TOKEN env varPersonal access token read from the environment at process startAny environment, including Replit Shell, Replit Deployments, and standard CIToken typed into the wrong Secrets store, missing scope, or copied with a trailing newline that breaks the Authorization header

    Per Expo's note on building on CI, the EXPO_TOKEN path is the documented default for any container that lacks a browser. Replit fits that description cleanly: the workspace runs in a remote container, and your browser tab cannot route a callback back into it.

    How do you read the View Log output to tell what is actually wrong?

    The View Log link is more useful than it looks once you stop treating it as a login wall.

    If the page asks you to sign in and then shows an empty log after sign-in, the build never started; the CLI is still waiting for the authentication handshake. The fix is the EXPO_TOKEN route described above.

    If the page asks for sign-in, accepts the credentials, and then shows a log that begins with Spawning and stops, the build started but the CLI session lost the token mid-stream. The Replit Shell process probably exited before the upload completed. Run the command inside nohup, or pin the Shell tab open until the upload step finishes.

    If the page shows a log that ends at the Submit to App Store step with a credentials error, the deploy reached EAS Submit but failed at the App Store Connect API key step. The token authenticated against Expo, but the App Store Connect API key referenced in your eas.json is missing from Replit Secrets, or its issuer ID is wrong.

    A short rule for the page: if the View Log link sends you back to the Expo sign-in page, the CLI has no Expo session. If it shows progress and then stops, it has the session and is failing further down the pipeline.

    What about EAS Submit and store credentials from Replit?

    The same pattern applies to eas submit, the hosted store submission service, with one extra wrinkle: store credentials.

    For iOS, EAS Submit needs an App Store Connect API key (a .p8 file), an issuer ID, and a key ID. Replit's editor Secrets can hold the key ID and issuer ID as plain strings, but the .p8 file usually needs to be base64-encoded into a Secret and decoded at runtime, or written into a private Replit file before the submit step runs. EAS Submit reads the key path from eas.json and will fail with an authentication error if the key is missing.

    For Android, EAS Submit needs a service account JSON file with Google Play Console permissions. The same pattern applies: base64-encode the JSON, store it as a Secret, decode it to a known path before the eas submit call, and reference that path in eas.json.

    For a security read of the compiled .apk or .ipa before EAS Submit hands the binary to the store, PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission scanning of AI-coded mobile builds against the OWASP MASVS controls. It does not handle the Expo authentication itself, but it flags the high-risk patterns that commonly appear in Replit-generated Expo projects: hardcoded API keys in the bundle, missing Android Network Security Config, and SDKs that need an iOS Privacy Manifest entry to clear Apple's automated review.

    What to watch out for

    • A token with a trailing newline silently fails. A paste from the Expo dashboard can include a newline that breaks the Authorization: Bearer header. Trim the value before saving the Secret, or recopy with a known-clean keyboard shortcut.
    • Editor Secrets do not propagate to Replit Deployments automatically. A working local CLI run is not proof that a deployed CI step has the same token. Both panes need the value.
    • Personal access tokens are account-wide. Anyone who can read the Secret can run actions on every project under your Expo account. For agency or contractor work, create a robot user with a scoped role and a separate token.
    • The eas-cli caches a stale session in ~/.expo. If you switched accounts on the local machine and copied the project to Replit, an old session file in the workspace can override EXPO_TOKEN until you delete it.
    • The View Log link can also fail because Replit's outbound network blocks a CDN. This is rare, but a check of status.replit.com before further diagnosis avoids an hour spent on the wrong root cause.

    Key takeaways

    • A Replit Expo deploy that hangs on the View Log login page is an authentication symptom, not a deploy failure. The CLI is waiting for an Expo session that the browser handshake cannot deliver to a containerized callback port.
    • A personal access token stored as EXPO_TOKEN in Replit Secrets is the documented path, per Expo's CI authentication guidance, and it removes the browser dependency for both eas build and eas submit.
    • Editor Secrets and Publishing pane Secrets are separate stores. A token visible in the Shell is not necessarily visible to a deployed web service that calls eas submit later.
    • Treat the View Log page as a diagnostic, not a login wall. Empty log after sign-in means no session; progress that stops mid-pipeline means a later step, often store credentials, is failing.
    • For teams that want an external read of the compiled .apk or .ipa before EAS Submit uploads the binary, PTKD.com (https://ptkd.com) is one of the platforms focused on pre-submission scanning of AI-coded mobile builds for OWASP MASVS-aligned issues.
    • #replit
    • #expo
    • #eas-cli
    • #deployment
    • #authentication
    • #expo-token
    • #ai-coded-apps

    Frequently asked questions

    Why does the View Log link redirect me to the Expo login page?
    The eas-cli prints the View Log URL while it waits for an Expo session. If no EXPO_TOKEN is set, the CLI expects your browser to deliver a session token back to a port inside the Replit container. That container is not reachable from your laptop, so the sign-in page loops back to itself. Setting EXPO_TOKEN in Replit Secrets removes the browser step entirely and the loop disappears.
    Is EXPO_TOKEN safer than logging in with my password on Replit?
    Yes, in two ways. The token does not expose your account password to the Replit Shell, and Expo lets you revoke it from the Access Tokens dashboard without ending other sessions or resetting credentials. For shared projects, create a robot user with a scoped role and issue a token from that account, so the human owner can leave the project without the token following them out.
    Does the EXPO_TOKEN secret go in Replit Secrets or in eas.json?
    Replit Secrets. The EXPO_TOKEN value is account-scoped and should never sit in a file committed to your repository. The eas.json file is for build profile configuration, not secrets, and is readable by anyone who clones the project. Replit Secrets are injected as environment variables into the running Shell process, which is exactly where the eas-cli reads EXPO_TOKEN from at startup.
    What if my deploy still fails after I set EXPO_TOKEN correctly?
    Check three things. The Secret value has no trailing newline; a paste from the dashboard often includes one and breaks the Authorization header. The token has not been revoked on the Expo dashboard. The ~/.expo cache directory in the Replit workspace does not hold a stale session from a previous login; if it does, delete it and rerun the command from a fresh Shell session.
    Can I run eas submit from a deployed Replit web service the same way?
    Yes, but the token must live in the Publishing pane Secrets, not only the editor Secrets. The two stores are separate. A deployed web service that calls eas submit from a route handler reads the deployment environment, so a missing EXPO_TOKEN there reproduces the same View Log loop you first saw in the editor Shell. Copy the secret into both panes before the next deploy.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free