Duplicate block
Refuse ticket creates that repeat an open ticket: what can block, how to pick the threshold from your own data, and what automated creators must handle.
The duplicate block refuses a ticket create that looks like a duplicate of an existing ticket, so the same work is not filed twice. It is off until you set Admin -> System settings -> Block duplicate tickets at similarity above 0. Without it orboto still warns about similar tickets on every create; the block turns the strongest of those warnings into a refusal.
Added in v0.203.0 What can refuse a create, and what cannot:
| Match | Shown as | Can it block? |
|---|---|---|
| AI embedding match on an open ticket (to do, in progress, in review) | a percentage, for example "96% AI match" | Yes, at or above your threshold |
| AI embedding match on a closed ticket | a percentage | No. A create that resembles a closed ticket is a recurrence or a regression, not a duplicate. It stays a warning. |
| Full-text match | "text match", without a percentage | No. A text rank is relative: the best text match always scores 1.000, whatever it says. |
When the block is on but the check found only text matches - a new project whose tickets are not embedded yet, or an outage of your embedding provider - the create goes through with a "duplicate check degraded" warning. The system settings page shows how many creates ran degraded in the last 7 days. A number that keeps climbing means the embedding pipeline needs attention, not a lower threshold.
Pick the threshold from your own data
Added in v0.203.0 Do not guess the value. The report under the threshold field computes, for every value from 0.80 to 0.99, how many legitimate creates the block would have refused and how many true duplicates it would have caught - from the duplicate reviews your instance already stored.
- Open Admin -> System settings and scroll to the duplicate block report (or run
orboto ticket duplicate-report). - Read the recommendation. It is the highest threshold that catches the most true duplicates while refusing at most the refusal budget - by default 0.5 % of legitimate creates - and it is never below 0.90. On a tie it takes the higher threshold, which catches the same and refuses no more.
- If no threshold stays inside the budget, the report recommends the one with the lowest refusal rate and says so. Until the window holds at least 200 embedding-decided legitimate reviews and 5 true duplicates it recommends nothing: a number picked from so few reviews would be noise.
- Enter the value, and look at the report again after two weeks.
How the report counts: a true duplicate has the same title as an older ticket in the same project; legitimate work is a ticket that reached Done or In review and is not a duplicate. Reviews stored before the match mode was recorded appear in their own column and are left out of the recommendation. The scan is bounded by a window in days (default 30) and by the 5,000 newest reviews; the response says which bound applied.
The report is also available as GET /admin/tickets/duplicate-threshold-report (permission admin:system:read), with refusalBudgetPercent between 0.1 and 5, and in the in-app AI chat.
Before you switch it on: automated creators
A refused create answers 409 with errorKey: "errors.tickets.duplicate_blocked" and carries the candidates, the threshold and which ticket decided. Anything that files tickets by itself - a monitoring alert intake, a script, an integration - has to handle that answer. A creator that treats the 409 as a failure loses the work it was filing; an alert intake loses the alert.
It must do one of two things:
- Comment on the open ticket the answer names, or
- retry with
allowDuplicate=trueand aduplicateJustificationthat says why it is not a duplicate (CLI:--allow-duplicate --duplicate-justification "...").
People and agents see the same refusal as a message that names the deciding ticket and the flag to add - see Creating tickets from the CLI.