{"record":{"id":"8ebabcf9a06083d4","repo":"BerriAI/litellm","slug":"login-did-not-produce-a-usable-token-cannot-start","errorCode":null,"errorMessage":"Login did not produce a usable token; cannot start `lite up`.","messagePattern":"Login did not produce a usable token; cannot start `lite up`\\.","errorType":"exception","errorClass":"UpError","httpStatus":null,"severity":"error","filePath":"litellm/proxy/client/cli/commands/up.py","lineNumber":175,"sourceCode":"\n\ndef _ensure_fresh_login(ctx: click.Context) -> None:\n    base_url: Final = ctx.obj[\"base_url\"].rstrip(\"/\")\n    token_data = load_token()\n    if token_data and token_data.get(\"base_url\") == base_url and is_cli_token_fresh(token_data):\n        return\n\n    if not sys.stdin.isatty():\n        raise UpError(\n            \"No fresh LiteLLM login found for this proxy. Run `lite login` first (apiKeyHelper \"\n            \"reads this token on every Claude Code request).\"\n        )\n\n    click.echo(\"No fresh LiteLLM login found for this proxy; starting login...\")\n    ctx.invoke(login)\n    token_data = load_token()\n    if not token_data or token_data.get(\"base_url\") != base_url or not is_cli_token_fresh(token_data):\n        raise UpError(\"Login did not produce a usable token; cannot start `lite up`.\")\n\n\ndef _restore_and_report() -> None:\n    record: Final = restore_claude_settings()\n    if record is None:\n        click.echo(\"Nothing to restore.\")\n        return\n    if record.existed:\n        click.echo(f\"Restored {CLAUDE_SETTINGS_PATH} to its original contents.\")\n    else:\n        click.echo(f\"Removed {CLAUDE_SETTINGS_PATH} (it did not exist before `lite up`).\")\n\n\n@click.command(name=\"up\")\n@click.pass_context\ndef up(ctx: click.Context) -> None:\n    \"\"\"Route every Claude Code session through your LiteLLM proxy until stopped.\n","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/proxy/client/cli/commands/up.py#L157-L193","documentation":"Raised by `lite up` after it invoked the interactive login flow (ctx.invoke(login)) but the reloaded token still fails the usability check: missing, wrong base_url, or stale per is_cli_token_fresh. It means the login flow returned without raising yet did not persist a token usable for this proxy — e.g. the browser SSO was never completed, or the token that landed in ~/.litellm/token.json belongs to a different server. `up` aborts rather than patch Claude Code settings with an apiKeyHelper that would fail on every request.","triggerScenarios":"Canceling or never opening the browser during `lite login`'s device/SSO flow; logging in against a different --base-url than the one `up` targets; the login poll finishing without writing token.json; a concurrent process (logout, second login) overwriting the token file between login and the re-check.","commonSituations":"Headless/SSH session with no browser so SSO never completed; clock skew on the machine making a just-issued token appear stale; proxy behind a URL rewrite so the stored base_url differs from the CLI's; two terminals running LiteLLM logins against different proxies clobbering one token.json.","solutions":["Run `lite login` standalone in the same terminal against the same proxy, complete the browser flow, and confirm `lite auth print-token --base-url <url>` prints a token","Verify ~/.litellm/token.json afterwards: `base_url` must exactly match the proxy `up` uses and `timestamp` must be fresh","If no browser can open on this machine, run `lite login` where one can and copy ~/.litellm/token.json (mode 0600) over","Check for a concurrent LiteLLM login/logout (CI job, another terminal) rewriting the token file"],"exampleFix":"# before\nlite up\n# \"No fresh LiteLLM login found; starting login...\"\n# UpError: Login did not produce a usable token; cannot start `lite up`.\n\n# after\nlite login --base-url https://proxy.internal   # complete SSO in the browser\nlite auth print-token --base-url https://proxy.internal   # sanity check\nlite up","handlingStrategy":"retry","validationCode":"import subprocess\n\ndef ensure_login() -> None:\n    if subprocess.call([\"lite\", \"auth\", \"print-token\", \"--base-url\", BASE_URL]) != 0:\n        subprocess.check_call([\"lite\", \"login\", \"--base-url\", BASE_URL])  # interactive repair\n        subprocess.check_call([\"lite\", \"auth\", \"print-token\", \"--base-url\", BASE_URL])  # verify","typeGuard":null,"tryCatchPattern":"import subprocess, sys\nfor attempt in (1, 2):\n    rc = subprocess.call([\"lite\", \"up\"])\n    if rc == 0:\n        break\n    if attempt == 1:\n        subprocess.call([\"lite\", \"login\"])  # one interactive repair, then one retry\n    else:\n        sys.exit(\"`lite up` failed twice — inspect ~/.litellm/token.json manually\")","preventionTips":["Confirm `lite auth print-token --base-url <proxy>` succeeds before starting `lite up`","Ensure a browser can open on the machine running login (or run login elsewhere and copy token.json with mode 0600)","Avoid concurrent `lite login`/`lite logout` in other terminals while `up` is starting"],"tags":["litellm","cli","sso","login-failure"],"backgroundTag":"sso-login-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}