# bracketeer Error Catalog

    library(bracketeer)

This catalog lists common errors with likely causes and direct fixes. Errors include actionable identifiers (stage IDs, match IDs, participant counts) wherever possible.

## 1) Infeasible transition count

Symptom: `validate()` or `build()` fails because the selector would pick more participants than are available from the source stage.

    my_spec <- spec() |>
      round_robin("groups") |>
      single_elim("finals", take = top_n(8))

    validate(my_spec, n = 6)
    # Error: stage 'finals' requires 8 participants via `top_n(8)` but source
    # stage 'groups' can produce at most 6. Adjust the selector or increase
    # participant count (currently n = 6).

Fix:

- Reduce `n` in `top_n(n)` to fit the available pool, or
- increase the participant count passed to `validate()` / `build()`.

## 2) `top_per_group()` on a non-grouped stage

Symptom: Error when a per-group selector is used on a stage without group structure.

    trn <- tournament(paste("Team", 1:8)) |>
      round_robin("league") |>
      single_elim("playoffs", take = top_per_group(2))
    # Error: `top_per_group()` requires the source stage 'league' to have
    # groups, but it was defined without `groups =`. Use `top_n()` for flat
    # standings, or add `groups =` to the source stage.

Fix:

- Use `top_n(n)` if the source stage is a flat round-robin, or
- add `groups = k` to the source stage verb if group play is intended.

## 3) `previous_stage()` on the first stage

Symptom: Error when the first stage verb implicitly or explicitly uses `previous_stage()` but there is no preceding stage.

    spec() |>
      single_elim("finals", from = previous_stage())
    # Error: `previous_stage()` in stage 'finals' resolved to no prior stage.
    # 'finals' is the first stage in this spec. Provide an explicit `from =`
    # or add a source stage before it.

Fix: This only happens if you set `from = previous_stage()` explicitly on the first stage, or if you call a stage verb on an empty spec without a source. Add the source stage first:

    spec() |>
      round_robin("groups") |>
      single_elim("finals", take = top_n(8))  # from = previous_stage() is implicit, resolves to "groups"

## 4) Explicit `from =` stage ID not found

Symptom: Error when a `from =` argument references a stage that does not exist.

    tournament(paste("Team", 1:16)) |>
      round_robin("groups") |>
      single_elim("finals", from = "typo_stage", take = top_n(8))
    # Error: `from = "typo_stage"` in stage 'finals' references a stage that
    # does not exist. Known stages: groups. Check the stage ID spelling.

Fix: Check the stage ID spelling. Use the exact string passed to the source stage verb.

## 5) Overlapping selectors in a branch

Symptom: Two stages branching from the same source both select the same participants, causing a conflict.

    tournament(paste("Team", 1:16)) |>
      round_robin("groups") |>
      single_elim("championship", from = "groups", take = top_n(8)) |>
      single_elim("consolation",  from = "groups", take = top_n(8))  # same 8!
    # Error: stages 'championship' and 'consolation' both consume overlapping
    # participants from source 'groups'. Use `remaining()` for the second
    # branch to select the leftover pool, or adjust selectors to be disjoint.

Fix: Use `remaining()` for the second branch:

    tournament(paste("Team", 1:16)) |>
      round_robin("groups") |>
      single_elim("championship", from = "groups", take = top_n(8)) |>
      single_elim("consolation",  from = "groups", take = remaining())

## 6) Overwrite blocked by downstream materialization

Symptom: Attempting to change a result after a downstream stage has already been materialized from it.

    # After all group results have been entered and "knockout" has materialized:
    trn <- trn |> result("groups", match = 1, score = c(0, 2))
    # Error: result for match 1 in stage 'groups' cannot be overwritten because
    # downstream stage 'knockout' has already been materialized from 'groups'.
    # Use teardown(trn, "knockout") first to unlock result editing.

Fix: Use `teardown()` to un-materialize the blocking downstream stage, then re-enter the corrected result:

    trn <- teardown(trn, "knockout")
    trn <- trn |> result("groups", match = 1, score = c(0, 2))
    # "knockout" will re-materialize automatically when groups is complete again.

## 7) `validate()` fails for duplicate stage IDs

Symptom: Two stage verbs use the same stage ID.

    spec() |>
      round_robin("stage") |>
      single_elim("stage")  # duplicate!
    # Error: stage ID 'stage' is already registered. Stage IDs must be unique.
    # Provide a distinct ID for each stage.

Fix: Use unique IDs for every stage.

## 8) Invalid `score` argument

Symptom: `result()` receives a score that is not a numeric vector of at least length 2.

    trn <- trn |> result("groups", match = 1, score = 2)
    # Error: `score` must be a numeric vector of length >= 2 (e.g., c(2, 1)).
    # Received: a single value (2). Did you mean score = c(2, 1)?

Fix: Always pass `score` as a vector: `score = c(home_score, away_score)`.

## Operational checklist

1. Define: `tournament(teams) |> <stage_verbs>`.
2. (Optional) Validate: `validate(spec, n)` before building.
3. Inspect schedule: `matches(trn, stage)`, `stage_status(trn)`.
4. Enter results: `result(trn, stage, match, score = c(x, y))`.
5. Auto-advance is the default — check `stage_status(trn)` to confirm.
6. Use `teardown(trn, stage)` if you need to correct results after advancement.
7. Finish: `winner(trn)`, `rankings(trn)`, `routing_log(trn)`.