Similar issues and grouping suggestions
Bucker groups events into issues by fingerprint. Two issues that are really one bug (the same failure reached by a slightly different stack, or reworded by a different library version) are found a second way: by comparing what the issues say. The result appears in three places:
- Similar issues on an issue page, with any fix recorded for the neighbours.
- Grouping suggestions: pairs of issues that look like the same bug, waiting in the project's review queue (Grouping, Review queue).
- Merge, in the queue and in the issue stream, to fold the duplicates together.
Nothing is ever merged because it looked similar. A suggestion is a question for a person. The only automatic merging in the product is the opt-in auto-merge policy, which stays off until an organization's own confirmed and rejected pairs show it is accurate enough (the precision gate on the same screen).
What is compared
Each issue is turned into a 768-number vector from its exception type and message, its title and its culprit. Nothing else: not event payloads, not user data, not breadcrumbs, not source code. Two issues are close when their vectors are.
Two providers can make the vectors.
| Provider | What it understands | Needs |
|---|---|---|
| Local (default) | Shared words, identifiers and character runs. getUserById and findUserById match; two descriptions of the same failure in different words do not |
nothing |
| Hosted | Meaning, so a message and its rewording are close | an API key, and a person to get one |
The local provider is deterministic and offline, which is why it is the default and the
fallback. The hosted one speaks the OpenAI-compatible POST /v1/embeddings shape, so it works
with OpenAI, Azure OpenAI, Voyage, Mistral, Together, vLLM and Ollama.
Turning the hosted provider on
This is a step for a person with an account at the provider. Bucker cannot get a key.
- Create an API key with the provider.
- On the API, worker and MCP services set
EMBEDDING_PROVIDER=hostedandEMBEDDINGS_API_KEY, with identical values: every neighbour query filters on the model name, so a service that resolves a different provider silently finds nothing. Optional:EMBEDDINGS_API_URL(defaulthttps://api.openai.com/v1/embeddings) andEMBEDDINGS_MODEL(defaulttext-embedding-3-small). The model must honour thedimensionsrequest field and return 768; a model that cannot is refused, never padded. - Deploy. Vectors made by the old provider are rebuilt automatically, a project at a time, because every vector records the model that made it and two models are never compared.
If EMBEDDING_PROVIDER=hosted is set and the key is not, Bucker keeps grouping on the local
provider and says so: the worker logs a warning at boot, and a scan reports why it ran on the
local provider. Silently grouping worse is the failure this avoids; refusing to group is worse
still.
What leaves your deployment
With a hosted provider, an issue's exception type, message, title and culprit are sent to it when the issue is created and when its vector is rebuilt. Two switches keep things local:
- An organization with AI features turned off (its AI switch) always uses the local provider, and nothing about its issues leaves the deployment.
- Source code is never sent to the hosted provider by the codebase index unless the
deployment sets
EMBEDDINGS_ALLOW_SOURCE_CODE=true, a separate decision from grouping.
Bucker's hosted service embeds issues only: it leaves EMBEDDINGS_ALLOW_SOURCE_CODE unset, so
code retrieval for root-cause analysis and fix context stays on the local provider. Sending source
code too would wait on a per-organization AI-switch check on the codebase path, which does not exist
yet.
If the provider fails while an issue is being embedded (an outage, a revoked key), the embedding is not stored, and the next nightly pass embeds it; it is not replaced by a local vector, which would put a weaker vector into a hosted index under the wrong name.
The nightly pass
A worker pass runs about once a day. For every project with at least two issues seen in the
last week it embeds any issue that has no vector from the current provider (up to 500 per
project per night, busiest projects first, 200 projects per night, so a large backlog drains
over several nights rather than in one bill), and then scans for similar pairs at the usual
threshold. Pairs you already decided are never asked again. GROUPING_SWEEP_ENABLED=false
turns the pass off; Scan for duplicates in the queue still runs one project on demand.
Merging suggestions
Tick the suggestions that are the same bug and press Merge N selected. Each is confirmed (so it counts toward the precision statistic) and merged, up to 50 at a time. For each pair the older issue survives, because it holds the short ID people have already pasted into tickets.
- A pair that cannot be merged (one side was merged elsewhere, deleted, or someone else decided it first) is skipped with its reason and stays in the queue.
- Every merge is audited and can be undone from Grouping, Merge history, with the counters restored exactly.
- It needs the right to triage issues in the project.
In the issue stream, select two or more issues of one project and choose Merge to pick the survivor yourself.
POST /orgs/:org/projects/:project/grouping-suggestions/merge
{ "suggestionIds": ["...", "..."] }
The response lists, per suggestion, merged or skipped with a reason.
What this is not
Bucker does not train or fine-tune a model, and it does not merge on similarity alone. The published wrong-merge rate of automatic embedding merges is high enough that the product keeps a person in the loop until your own data says otherwise.