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

# Troubleshooting

> Common Flash errors, why they happen, and how to fix them.

Most `flash` errors print one clean line; add the global `--debug` flag before
the subcommand (e.g. `flash --debug train config.toml`) for the full traceback.

## Installation & CLI

<AccordionGroup>
  <Accordion title="flash: command not found">
    The CLI installs a single `flash` command. Its install location must be
    on your `PATH`.

    * If you installed with `uv tool install freesolo-flash`, make sure uv's tool
      bin directory is on your `PATH` (run `uv tool update-shell`, then restart
      your shell).
    * Confirm the install with `flash version`.
  </Accordion>

  <Accordion title="I installed `flash` but it's the wrong tool">
    The CLI is published to PyPI as **`freesolo-flash`**. The bare `flash` name
    belongs to an unrelated project. Reinstall the right one:

    ```bash theme={null}
    uv tool install freesolo-flash
    ```
  </Accordion>
</AccordionGroup>

## Authentication

<AccordionGroup>
  <Accordion title="flash login fails or commands report 401 / invalid key">
    Commands that contact Freesolo authenticate with a **Freesolo API key**,
    verified at login. Local `flash train --cost` does not submit.

    * Create a key in your dashboard at [freesolo.co](https://freesolo.co).
    * Log in once: `flash login --api-key <your-key>` (or set `FREESOLO_API_KEY`
      instead of passing `--api-key`).
    * Confirm who the stored key resolves to: `flash whoami`.
  </Accordion>

  <Accordion title="Pointing at a non-default Freesolo deployment">
    By default the CLI talks to `https://api.freesolo.co`. To target a different
    deployment, set `--freesolo-url` (or `FREESOLO_BASE_URL`) at login.
  </Accordion>
</AccordionGroup>

## Environments

<AccordionGroup>
  <Accordion title="flash env push fails">
    The folder you push must contain an `environment.py` file with a
    `load_environment()` function that returns a Freesolo environment. Then:

    ```bash theme={null}
    flash env push --name math math
    ```

    It prints the published id (`your-org/math`) to put in your config's
    `[environment] id`. If you pass `--name namespace/name`, the namespace must
    match your Freesolo org; otherwise pass a bare name such as `math`.
  </Accordion>

  <Accordion title="ModuleNotFoundError: No module named 'freesolo' (local authoring)">
    Managed training workers have the Freesolo SDK when they import a published
    environment. Your local Python environment does not get that SDK automatically
    from the `flash` CLI. Install it locally to run or test `environment.py`
    directly. Local `flash train --cost` parses the config without importing the
    environment, and authenticated server-side `--dry-run` starts no GPU worker:

    ```bash theme={null}
    uv pip install freesolo
    ```

    To pull a published env into your project for local work, use
    `flash env pull your-org/your-env`.
  </Accordion>

  <Accordion title="Worker import fails with ModuleNotFoundError">
    `flash train --dry-run` runs server-side submit preflights, but it does not
    execute the GPU worker or prove every environment dependency is installed.
    If `flash log <run-id>` shows
    your `environment.py` failed while importing a task library, add that
    package to `[environment].pip`, publish the environment, and submit again:

    ```toml theme={null}
    [environment]
    id = "your-org/your-env"
    pip = ["math-verify>=0.8.0"]
    ```

    Only list packages your environment imports. Flash does not install worker
    dependencies from a `pyproject.toml`, `requirements.txt`, or lockfile bundled
    with the environment; keep managed-run dependencies in `[environment].pip`.
  </Accordion>

  <Accordion title="[environment].pip breaks training startup">
    `[environment].pip` is for task dependencies imported by your environment. Do
    not pin Flash's managed training stack there, such as `torch`, `trl`, `vllm`,
    `peft`, or `bitsandbytes`, unless your environment directly imports that
    package. Extra pins can conflict with the worker's tested training recipe.
    Remove the pin and resubmit.
  </Accordion>

  <Accordion title="flash env pull says the archive is too large">
    Pull the specific file you need instead of the whole environment:

    ```bash theme={null}
    flash env pull your-org/your-env environment.py -o environment.py
    flash env pull your-org/your-env dataset/eval.jsonl -o eval.jsonl
    ```

    Keep published environments focused on source, small sidecars, and datasets
    needed by the run. Do not publish virtualenvs, local caches, model weights,
    or generated artifacts.
  </Accordion>

  <Accordion title="I republished an environment and want to verify the data">
    Use `flash env pull` to inspect the exact packaged file:

    ```bash theme={null}
    flash env pull your-org/your-env dataset/train.jsonl -o train.jsonl
    ```

    For clean A/B experiments, publish changed datasets under a fresh env name
    so old runs, new runs, and local files are easy to tell apart.
  </Accordion>

  <Accordion title="Environment won't import / name collision">
    If your environment module shares a name with an installed Python package, it
    can shadow or be shadowed by that package. Keep helper module names distinct
    from installed packages.
  </Accordion>

  <Accordion title="What id do I reference in my config?">
    The `[environment] id` must be a published Freesolo environment id, produced
    by `flash env push`, for example `your-org/your-env`.
    A local file path is not a valid id, so publish it first or reference an
    existing published id. Use `flash env pull your-org/your-env` only when you
    want a local copy to edit or inspect.
  </Accordion>
</AccordionGroup>

## Configuration

<AccordionGroup>
  <Accordion title="unsupported model '...'">
    `model` must be one of the ids in the curated catalog. List the valid ids:

    ```bash theme={null}
    flash models
    ```

    Managed runs train catalog models only. See [Supported models](/reference/models).
  </Accordion>

  <Accordion title="Unknown config key or section rejected">
    Flash rejects unknown config sections and `[train]` keys **at parse time**.
    Check the key against the
    [configuration reference](/reference/configuration) and run authenticated
    server-side validation:

    ```bash theme={null}
    flash train config.toml --dry-run
    ```

    Dry-run also reports client/server `[train]` schema differences.
  </Accordion>

  <Accordion title="unsupported algorithm">
    `algorithm` must be `sft` (the default), `grpo`, or `opd`. Fix the value and
    re-validate with `--dry-run`.
  </Accordion>

  <Accordion title="Run rejected: training context exceeds serving context">
    Flash rejects a run at submit when its training context is longer than the
    base model's serving context (`max_model_len`). A LoRA trained longer than it
    is served wastes compute and learns positions never used at inference. SFT
    checks `train.max_context_tokens`; GRPO and OPD check the rollout prompt plus
    `max_completion_tokens`. Most models serve at 32768; `Qwen/Qwen3.6-35B-A3B`
    serves at 4096. Lower `max_context_tokens` and, for GRPO/OPD,
    `max_completion_tokens` to at or below the serving context. See [context
    window](/reference/models#context-window-and-lora-rank).
  </Accordion>

  <Accordion title="Warm-start rank, alpha, or revision mismatch">
    The source LoRA rank and alpha are authoritative. Remove both
    `train.lora_rank` and `train.lora_alpha` when using `init_from_adapter`. A
    pinned `model_revision` must match the source exactly. Use server-side
    `--dry-run` to resolve and validate the source; local `--cost` may use
    defaults and warn.
  </Accordion>

  <Accordion title="The run used a different GPU than expected">
    GPU selection is automatic unless you set `[gpu] exact_type` to an active
    validated class from `flash gpus`. Add `provider = "runpod"`, `"lambda"`, or
    `"vast"` only when the provider must also be fixed. These constraints persist
    across retries and cost estimates.
  </Accordion>
</AccordionGroup>

## Run fit and resource use

<AccordionGroup>
  <Accordion title="GRPO costs or fits differently than SFT">
    Expected. GRPO samples multiple completions, scores them, and updates from
    that group of attempts. For the same model, it usually needs more room and
    costs more than SFT. If a GRPO run is too expensive or too large, use a
    smaller model, reduce `group_size`, reduce `max_completion_tokens`, reduce
    `max_context_tokens`, or start with SFT.
  </Accordion>

  <Accordion title="Pre-flight says the run is too large">
    The usual causes are long context, long generated completions, a large GRPO
    `group_size`, or a larger base model than the task needs. Reduce
    `max_context_tokens`, `max_completion_tokens`, or `group_size`, or switch to
    a smaller model.
    If you recently enabled `thinking = true`, reasoning and the final answer
    share the same token budget.
  </Accordion>
</AccordionGroup>

## Training runs

<AccordionGroup>
  <Accordion title="When am I charged for a run?">
    Flash checks your prepaid org balance against the pre-flight estimate before
    submit, then bills successful runs at the quoted Flash cost. Cancelled runs
    are repriced to the training steps they reached, and setup time is reported
    separately without being billed. Preview the estimate before you submit:

    ```bash theme={null}
    flash train config.toml --cost
    ```
  </Accordion>

  <Accordion title="Run submit reports insufficient balance">
    Add funds or reduce the run estimate before submitting again. Smaller base
    models, fewer GRPO/OPD epochs, lower `group_size`, shorter
    `max_completion_tokens`, and SFT smoke tests are the fastest ways to lower the
    pre-flight estimate.
  </Accordion>

  <Accordion title="GRPO reward is stuck at 0">
    The task is too hard for the model at its current ability: if no rollout ever
    scores, there's nothing for GRPO to reinforce. Try a stronger or larger base
    model, make the task easier to start, or double-check that your reward returns
    a positive reward for good answers.
  </Accordion>

  <Accordion title="Reward is stuck at 1 (or never moves)">
    Usually the reward is not discriminative: it scores almost everything the
    same. Make the reward function separate better answers from worse ones so GRPO
    has a spread of scores to learn from. See
    [Environments](/guides/environments/overview).
  </Accordion>

  <Accordion title="Reward collapses to ~0 with `thinking = true`">
    When `thinking = true`, the model emits a reasoning trace **before** its answer,
    and that trace counts against the **same `max_completion_tokens` budget** as
    the answer. A `max_completion_tokens` tuned for a non-thinking run is usually
    too small once reasoning is added: the reasoning eats the budget and the actual
    answer is truncated or never emitted. If your reward parses the answer (e.g.
    extracts a JSON object), it then sees nothing and scores \~0 across the board —
    even though the model is "working".

    Fixes:

    * **Raise `max_completion_tokens`** so the reasoning *and* the answer both fit
      (e.g. a task that needs \~200 answer tokens may need
      `max_completion_tokens = 2048` with thinking on), and make sure
      `max_context_tokens` is large enough to hold the prompt plus that budget.
    * Optionally set `thinking_length_penalty_coef` to nudge the model toward shorter
      reasoning so the answer reliably lands inside the budget.
    * Score the answer text by default. In thinking mode `response_text` remains
      string-compatible answer text and also exposes `response_text.completion`,
      `response_text.thinking`, and `response_text.raw` for rewards that intentionally
      inspect reasoning.

    The same trap applies to any **reasoning model you call as an LLM judge** from a
    reward: give the judge call enough `max_tokens` or it returns empty content and
    the judge silently scores 0.
  </Accordion>

  <Accordion title="Qwen3.5 thinking multi-turn SFT learns doubled thinking tags">
    In Qwen3.5 thinking mode, the chat template treats prior and next assistant
    turns differently: it strips literal `<think>` blocks from non-final assistant
    history, then pre-opens `<think>\n` in the next generation prompt. A naive
    multi-turn SFT transcript that puts `<think>...</think>` in every assistant
    turn can therefore train on a tag layout that inference will never render.
    The symptom is doubled, missing, or misplaced thinking tags, or an adapter that
    behaves differently in training-style evals than it does when served.

    Fixes:

    * For message-shaped multi-turn SFT targets, keep intermediate assistant turns
      as the actual code, tool, or action text only.
    * Put `<think>...</think>` plus the final answer only in the final assistant
      target.
    * Do not add a second opener for the template's pre-opened `<think>\n`. Flash's
      completion-only SFT masking uses the longest shared token prefix, so that
      pre-opened tag is treated as prompt text.
  </Accordion>

  <Accordion title="OPD run underperforms SFT, or its rollouts never terminate">
    OPD refines a model that already has the output format. Warm-start from a
    finished SFT run, and omit `lora_rank` and `lora_alpha` because the source
    values are authoritative:

    ```toml theme={null}
    [train]
    init_from_adapter = "<sft-run-id>"
    ```

    You can also use `"<sft-run-id>/step-N"` for a saved checkpoint. Verify that
    the selected teacher clearly beats the student on held-out task examples.

    There is no auxiliary EOS loss. For rollouts that reach
    `max_completion_tokens` without stopping:

    * Start from an SFT adapter with the desired stopping behavior.
    * Give the teacher a hard answer or reasoning budget in the system prompt.
    * Add `stop_sequences` when the task has reliable textual terminators.
    * Track `truncated_rollouts` to diagnose termination.

    OPD supports single- and multi-turn environments but not tool-calling ones,
    and `kl_penalty_coef` must be greater than `0`.
  </Accordion>

  <Accordion title="Did pressing Ctrl-C kill my run?">
    No. `Ctrl-C` during `flash train` **detaches** you; the run keeps going
    on Freesolo. Re-follow it any time, and cancel explicitly if you mean to:

    ```bash theme={null}
    flash runs              # state and cost of your runs
    flash log <run-id> -f       # re-follow the logs
    flash status <run-id>       # status and cost JSON
    flash cancel <run-id>       # stop it
    ```
  </Accordion>

  <Accordion title="flash cancel takes a long time to return">
    Expected. Cancellation waits for the managed worker to stop and clean up
    before confirming, which can take several minutes. The CLI waits this teardown
    out; the run is marked `cancelled` when it completes.
  </Accordion>

  <Accordion title="A capacity or resource-fit issue interrupted training">
    Flash uses bounded retries. SFT, GRPO, and OPD resume only from a validated
    full-state checkpoint at a clean optimizer-step boundary.

    OPD may start a replacement fresh only when Flash can prove that no earlier
    attempt may have mutated optimizer state. If checkpoint or mutation evidence
    is missing, incomplete, unreadable, incompatible, or ambiguous, replacement
    fails closed instead of searching for an older checkpoint or restarting from
    fresh state.

    Watch logs with `flash log <run-id> -f` or poll status with
    `flash status <run-id> -f`. If the same shape repeatedly fails before useful
    metrics, reduce `max_context_tokens`, `max_completion_tokens`, or `group_size`.
  </Accordion>
</AccordionGroup>

## Serving

<AccordionGroup>
  <Accordion title="Deploy fails: run has no run-level adapter">
    A run cancelled or preempted before finalizing has no final adapter, so a
    plain `flash deploy <run-id>` cannot serve it. The error lists the run's
    saved checkpoint steps and the exact command to use — deploy one of them
    instead:

    ```bash theme={null}
    flash checkpoints <run-id>
    flash deploy <run-id>/step-<N>
    ```
  </Accordion>

  <Accordion title="Deploy or the first request is slow">
    Every real deploy resolves an immutable revision and runs a bounded smoke
    before activating the stable alias. Large models can take a few minutes to
    warm and verify. A failed smoke leaves the alias unchanged. See [Deploy &
    chat](/guides/deploy-and-chat).
  </Accordion>

  <Accordion title="How is serving billed?">
    Serving is **billed per token** for requests. Prompt, completion, and cached
    prompt token rates are listed in [Supported models](/reference/models#serving-prices).
    `flash undeploy <run-id>` disables the alias and immutable revisions.
  </Accordion>

  <Accordion title="Calling the endpoint from my own code is rejected">
    Use `openai_base_url` from `flash deployments --json`, set `model` to the run
    alias or a full immutable revision, and pass your Freesolo API key.

    * `401`: missing or invalid key.
    * `402`: insufficient org balance.
    * `403`: the key's org does not own the adapter.
    * `503`: backend temporarily unavailable; retry with backoff.

    See [Use it from your own code](/guides/deploy-and-chat#use-it-from-your-own-code).
  </Accordion>
</AccordionGroup>

## Getting help

Still stuck? Add `--debug` to surface the full traceback, then reach out through
[freesolo.co/contact](https://freesolo.co/contact) with the run id (`flash runs`)
and the failing command.

## Next steps

<CardGroup cols={2}>
  <Card title="CLI reference" icon="terminal" href="/reference/cli">
    Flags and commands for every step.
  </Card>

  <Card title="Configuration reference" icon="gear" href="/reference/configuration">
    Valid config keys and sections.
  </Card>
</CardGroup>
