> ## Documentation Index
> Fetch the complete documentation index at: https://anaconda.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

export const TroubleshootSolution = ({children}) => <>
    <hr className="my-3 w-full" />
    <details className="mt-3">
      <summary className="cursor-pointer font-semibold text-base mb-1">
        Solution
      </summary>
      <div className="mt-2 ml-4" data-component-part="step-content">
        {children}
      </div>
    </details>
  </>;

export const TroubleshootCause = ({children}) => <details className="mt-3 mb-2">
    <summary className="cursor-pointer font-semibold text-base mb-1">
      Cause
    </summary>
    <div className="mt-2 ml-4" data-component-part="step-content">
      {children}
    </div>
  </details>;

export const TroubleshootTitle = ({children}) => <>
    <p className="m-0 font-semibold text-xl leading-tight mb-2" role="heading" aria-level={3}>
      {children}
    </p>
    <hr className="my-3 w-full" />
  </>;

export const Troubleshoot = ({children}) => <div className="callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border troubleshoot-admonition dark:troubleshoot-admonition" data-callout-type="troubleshoot">
    <div className="mt-0.5 w-4">
      <svg width="14" height="14" viewBox="0 0 640 640" fill="currentColor" className="w-4 h-4" aria-label="Troubleshoot">
        <path d="M541.4 162.6C549 155 561.7 156.9 565.5 166.9C572.3 184.6 576 203.9 576 224C576 312.4 504.4 384 416 384C398.5 384 381.6 381.2 365.8 376L178.9 562.9C150.8 591 105.2 591 77.1 562.9C49 534.8 49 489.2 77.1 461.1L264 274.2C258.8 258.4 256 241.6 256 224C256 135.6 327.6 64 416 64C436.1 64 455.4 67.7 473.1 74.5C483.1 78.3 484.9 91 477.4 98.6L388.7 187.3C385.7 190.3 384 194.4 384 198.6L384 240C384 248.8 391.2 256 400 256L441.4 256C445.6 256 449.7 254.3 452.7 251.3L541.4 162.6z" />
      </svg>
    </div>
    <div className="prose min-w-0 w-full">{children}</div>
  </div>;

When a command requires authentication and none is available, the CLI detects the error and, if running in an interactive terminal, offers to start the login flow automatically. If you decline, or if the session is non-interactive, the command exits non-zero with guidance on how to authenticate.

<Troubleshoot>
  <TroubleshootTitle>
    ### Login hangs on headless servers or SSH sessions
  </TroubleshootTitle>

  <TroubleshootCause>
    On versions of `anaconda-auth` older than 0.15.0, the default login flow attempts to open a web browser for OAuth authentication. If you are on a headless server, in an SSH session, or on any system without a graphical browser, this causes the login command to hang indefinitely.

    In `anaconda-auth` 0.15.0 and later, the device code flow is used by default, which does not require a local browser. If you are experiencing this issue, you are likely running an older version.
  </TroubleshootCause>

  <TroubleshootSolution>
    Update `anaconda-auth` to 0.15.0 or later, which uses the device code flow by default:

    ```sh theme={null}
    conda install "anaconda-auth>=0.15.0"
    ```

    If you cannot update, use one of the following workarounds:

    <AccordionGroup>
      <Accordion title="Enable device flow with an environment variable">
        Set the `ANACONDA_AUTH_USE_DEVICE_FLOW` environment variable before running the login command:

        ```sh theme={null}
        export ANACONDA_AUTH_USE_DEVICE_FLOW=1
        anaconda auth login
        ```

        The CLI prints a verification URL and a one-time code. Open the URL on any device with a browser, enter the code, and the login completes on the headless system.
      </Accordion>

      <Accordion title="Configure device flow permanently for a site">
        Use `anaconda sites modify` to enable device flow for the configured site:

        ```sh theme={null}
        anaconda sites modify --use-device-flow <SITE_NAME>
        ```

        After this, all future `anaconda auth login` calls for that site use device flow.
      </Accordion>

      <Accordion title="Use an API key environment variable">
        If you do not need interactive login (for example, in CI/CD pipelines or automated scripts), bypass the login flow entirely by setting an API key:

        ```sh theme={null}
        export ANACONDA_AUTH_API_KEY=$(anaconda auth api-key)
        ```

        On a system where you cannot run `anaconda auth api-key` directly, retrieve the key on another machine first and inject it through your platform's secrets management (for example, GitHub Actions secrets or a vault).
      </Accordion>
    </AccordionGroup>
  </TroubleshootSolution>
</Troubleshoot>

<Troubleshoot>
  <TroubleshootTitle>
    ### `TokenNotFoundError`
  </TroubleshootTitle>

  <TroubleshootCause>
    The CLI attempted to load an authentication token from the keyring for the target site, but no token was found. This typically occurs when you have not yet logged in, or when a previous `anaconda auth logout` removed the stored credentials. In an interactive terminal, the CLI prompts with "Continue with interactive login?" before failing.
  </TroubleshootCause>

  <TroubleshootSolution>
    Run `anaconda auth login` to authenticate and store a new token:

    ```sh theme={null}
    anaconda auth login
    ```

    For non-interactive environments (CI/CD pipelines, scripts), set the `ANACONDA_AUTH_API_KEY` environment variable instead:

    ```sh theme={null}
    export ANACONDA_AUTH_API_KEY=your-api-key
    ```
  </TroubleshootSolution>
</Troubleshoot>

<Troubleshoot>
  <TroubleshootTitle>
    ### `TokenExpiredError`
  </TroubleshootTitle>

  <TroubleshootCause>
    A token was found in the keyring, but it has expired. API keys have a configurable expiration period, and the CLI validates the token before making requests. In an interactive terminal, the CLI prompts with "Continue with interactive login?" to replace the expired token.
  </TroubleshootCause>

  <TroubleshootSolution>
    Run `anaconda auth login` to issue and store a fresh token:

    ```sh theme={null}
    anaconda auth login
    ```

    To configure the expiration period for new tokens, see the `api_key_expiration_days` setting in [Configuration](/docs/cli-reference/anaconda-auth/getting-started#configuration).
  </TroubleshootSolution>
</Troubleshoot>

<Troubleshoot>
  <TroubleshootTitle>
    ### `AuthenticationMissingError`
  </TroubleshootTitle>

  <TroubleshootCause>
    A request was made to a server endpoint that requires authentication, but no credentials were attached to the request. This can happen when a command reaches an authenticated API without first loading a token from the keyring or environment. In an interactive terminal, the CLI offers to start the login flow automatically.
  </TroubleshootCause>

  <TroubleshootSolution>
    Log in to store credentials for the target site:

    ```sh theme={null}
    anaconda auth login
    ```

    Alternatively, set the `ANACONDA_AUTH_API_KEY` environment variable:

    ```sh theme={null}
    export ANACONDA_AUTH_API_KEY=your-api-key
    ```
  </TroubleshootSolution>
</Troubleshoot>

<Troubleshoot>
  <TroubleshootTitle>
    ### `InvalidAuthentication`
  </TroubleshootTitle>

  <TroubleshootCause>
    Credentials were sent with the request, but the server rejected them. This usually means the stored API key has been revoked, rotated on the server side, or was issued for a different site. In an interactive terminal, the CLI offers to start the login flow to obtain a replacement token.
  </TroubleshootCause>

  <TroubleshootSolution>
    Force a new login to replace the invalid credentials:

    ```sh theme={null}
    anaconda auth login --force
    ```

    If you are targeting a specific site, include the `--at` flag:

    ```sh theme={null}
    anaconda auth login --force --at <SITE>
    ```
  </TroubleshootSolution>
</Troubleshoot>
