Skip to content

Issues

An issue is a group of errors that share a root cause. Fixter reads the errors already in your telemetry, parses their stack traces, and collapses the repeats into one tracked issue with a count, a culprit, and a history. Each new issue is investigated automatically, so by the time you look at one it usually already carries a root cause. From there you can hand it to your coding agent.

Ask your agent for list_issues to see what is broken, or open Issues in the app.

Issues are built from the telemetry you already send. Fixter watches your logs and traces for records that carry an error, so anything your services report through OpenTelemetry becomes an issue. There is no separate error-reporting SDK, no new endpoint, and nothing to add to your code. If telemetry is flowing, issues appear.

A single bug throws the same exception thousands of times. Fixter parses each stack trace and groups every occurrence that shares a root cause into one issue, so you see one row with a count of 3,412 rather than 3,412 separate lines.

Errors that differ only by an id stay together: Order 8f2c1a not found and Order b31e07 not found are one issue with a count of two, not two issues. The same goes for timestamps, request ids, hostnames, IP addresses, and anything else that changes on every occurrence, so Connection refused: db-3.internal and Connection refused: db-7.internal are one issue too.

Exceptions, log errors, and agent failures

Section titled “Exceptions, log errors, and agent failures”

The Issues list has three filters: Exceptions, Logs, and All. It opens on Exceptions.

Exceptions covers anything Fixter could classify. That includes thrown exceptions with a stack trace, and also failures that never produce one:

  • Agent and LLM failures. When a call to a model provider fails, or an agent stops early, or a tool it tried to run is missing, there is no stack trace to parse. Fixter recognises these by their shape rather than by their message text, so the same failure from different agent frameworks lands in one issue instead of scattering across hundreds. They carry the Agent runtime tag.
  • Database and server errors reported in a log line rather than thrown, in the common Postgres and ClickHouse server formats.

Logs covers the remainder: ERROR-level log lines that carry no exception and no recognisable shape, grouped by their message text.

A service can be perfectly healthy and still be invisible, and nobody files a ticket about an absence. Fixter scans for two of them and raises each as an issue:

  • Log severity never arrives. When more than 90 percent of a service’s logs land with no usable level, every ERROR it emits is indistinguishable from an INFO. Alert rules never match it, and the exception pipeline never sees it, so the service looks quiet because nothing can tell that it is not.
  • Logs carry no trace context. When fewer than a quarter of a service’s logs carry a trace id, no failure can be followed across a request boundary. This one only fires for services that already send spans, so it never doubles up with “this service has no tracing at all”.

Both need a week of data and a service that has been seen on at least five days before they raise anything, so a service you wired up yesterday is left alone. The fix is usually a few lines in the logging setup: Telemetry covers what each signal needs, and /fixter:onboard runs the same check from your editor.

Each issue carries the facts you need to judge and place it:

  • Exception type and message, and the culprit: the frame that threw and the frame that called it, so you know where to look before opening anything. When the error is thrown inside a library, the first names that library and the second is the line of your code that called into it.
  • Service and runtime. Runtime tags are JVM, Python, Node, .NET, Ruby, C++, Go, Postgres, Agent, and Log.
  • How much and how long: the event count, when it was first seen and last seen, and a daily trend so you can tell a steady background error from one that is spiking.
  • Environments: every deployment environment the issue has been seen in, with a count and first and last seen for each. See Environments.
  • Occurrences: the individual times it fired, each with its full stack trace, log level, exception message, any error object that was captured alongside it, and a link to the trace and log it came from.

Fixter records which deployment environment each occurrence came from, so one fault seen in staging and in production stays one issue, with a row per environment showing its count and when it was first and last seen there. The Issues list filters by environment, and each row carries a chip for every environment it has reached.

Announcements work per environment. A fault that has been in staging for a week still gets its own notification, and its own investigation, the first time it reaches production.

The environment comes from the deployment.environment.name resource attribute on your telemetry (the older deployment.environment spelling is read too). Occurrences without it are listed as Unknown, and the environment filter stays hidden until at least one issue carries an environment. OpenTelemetry setup shows how to set it.

Fixter sets an issue’s status from when it was seen, and you can override it:

StatusWhat it means
NewFirst seen within the last 3 days
OngoingSeen before that and still occurring
RegressedCame back after being resolved, or after at least 14 quiet days
ResolvedMarked fixed by you, or quiet for 15 days
SuppressedMarked by you as known; still counted, never notifies

Regressed is the one to watch: it is an error you had stopped thinking about, returning. Only one kind of regression notifies you: an issue you resolved yourself reopens on its very next event, with a notification saying when you resolved it and where it was seen again. An issue that comes back after going quiet on its own, whether or not the 15-day timer had resolved it, turns Regressed without a notification.

Above the list, a second row of tabs filters by status, separate from the Exceptions, Logs, and All filter. Its All tab holds New, Ongoing, and Regressed issues. Resolved and Suppressed sit at the right end of that row, with their counts. The Suppressed tab holds both issues you suppressed and issues a suppression rule hides.

Ask your agent, naming the issue or describing a set of them:

Resolve the NullPointerException in checkout-service, we shipped the fix this morning.

It calls set_issue_status for one issue, or set_issues_status for up to 50 at once, with one of three statuses (the tools call them RESOLVED, IGNORED, and ONGOING):

  • Resolved says the fix has shipped. If the error comes back, the issue regresses and you are notified.
  • Suppressed says the issue is known and not worth hearing about. It keeps counting events and recording environments, but it never notifies, not even when it reaches a new environment, and it stays out of the default list until you reopen it.
  • Ongoing reopens a resolved or suppressed issue.

In the app, open an issue and use its Status menu, which offers Resolve and Suppress on an open issue and Reopen on a closed one. To change several at once, tick their checkboxes in the Issues list (shift-click selects a range) and use the Resolve, Reopen, or Suppress action on the bar that appears.

A suppression rule silences a whole slice of issues at once, including ones that have not appeared yet: everything from a noisy service, every timeout in staging, every issue whose title mentions a third-party outage. An issue a rule matches is still tracked and counted, but it stays out of the list and never notifies. A rule lasts until you delete it.

Ask your agent:

Suppress every issue from the notifier service in staging.

It previews the rule with preview_suppression_rule to show how many issues it would hide, then saves it with create_suppression_rule.

In the app, open Suppression rules from the rule count link in the summary line above the Issues list, or choose Suppress by rule in an issue’s Status menu, which starts a rule from that issue’s exception type. A rule is written as a formula, and the editor completes field names and values with Tab and previews the matching issues as you type:

service = notifier and environment = staging
PartOptions
Fieldsservice, environment, exception type, title
Operators= matches, != excludes
Joiningand (every condition holds) or or (any one does), not both in one rule
ValuesWhole-value, case-insensitive. * stands for anything. Quote a value with spaces

A rule holds up to five conditions, and a value that is only * is refused. Some examples:

  • exception type = java.net.* hides every exception type under java.net.
  • service = payments and exception type != *TimeoutException hides everything from payments except its timeouts.
  • title = "*rate limit exceeded*" or service = batch-importer hides either.

environment = staging matches an issue that has been seen in staging, and a matching rule hides the whole issue, including its rows in other environments. environment != staging matches every issue that has never been seen in staging.

Deleting a rule, or editing it to match less, brings back the issues it alone was hiding. They return to the list at once and notify on their next event; nothing withheld in the meantime is sent. The rules page shows each rule’s coverage: how many issues it matches, how many were active in the last day, and how many notifications it has held back.

A suppressed issue stays suppressed until you reopen it or delete the rule. That is different from a suppression on an alert, which silences one alert signal for a set time and then expires.

When Fixter detects an issue it has not seen before, it announces it and starts an investigation of it. An AI agent reads the stack trace, then queries the telemetry and the source around it, and writes its findings onto the issue. You can watch it work: the issue page shows the steps as they happen. When the issue was announced in a Slack channel, a progress line in that message’s thread shows the same steps, and the brief is posted there once it has findings. New issues reach Slack only once you route them there, as the next paragraph explains.

New issues start out going to email only, so a workspace with no Slack connected still hears about them and a workspace with Slack does not get its channel filled with the first week of findings. Point the issue tracking source at your Slack channels under Settings > Notifications when you want them there. See Alerts for how routing works, since it is the same mechanism for all three sources.

Only genuinely new issues are announced, so the backlog you already had does not arrive as a wall of messages. A burst of new ones collapses into a single card with a single investigation behind it rather than one message each, and the message leads with the service and the exception, so you can tell from the notification alone whether it is yours. Its View logs link lands on the event that triggered it.

The brief you get back carries:

FieldWhat it gives you
Root causeOne sentence naming what broke and what it costs
MechanismThe chain from trigger to failure, with the source excerpt when the code was read. A file the agent names without having opened it is marked “not read this run”
EvidenceWhat was found and where, cited from the stack, logs, traces, metrics, or code
SeverityBreaking (something fails), Degraded (slower or retried), or Noise (nothing affected)
OriginYour code, a dependency, or infrastructure
ConfidenceHigh, medium, or low
Suggested fixWhat to change, when that is clear

Severity and origin are the two that save the most time on a full list: they separate the errors that are costing you something from the ones a handler already deals with, and they tell you whether the fix is even yours to make.

You can also run one on demand. The Investigate button on any issue starts a fresh investigation, and Re-investigate runs it again once you have changed something.

Open an issue and click Copy fix prompt. It is a complete claude "..." command, already filled in with everything the issue knows: the service, the exception and its culprit frames, the investigation’s root cause and evidence, the in-app stack frames from a real occurrence, the event count and trend, and the trace and log ids. Paste it into your terminal in the repository and your agent starts from the root cause.

The command also tells the agent how to pull live detail through the Fixter MCP tools if you have them connected: get_trace for the full distributed trace behind the error, get_log and get_log_neighbors for the raw record and what surrounded it, and run_sql for anything broader.

Your agent can read the whole list without you opening the app. Ask it something like:

What issues are breaking in production right now, and which have a root cause already?

It calls list_issues, which filters by status, service, environment, kind, or free text, sorts by events, first seen, or last seen, and flags which issues already carry an investigation brief. get_issue then returns one issue in full, including that brief. The same agent can resolve or suppress what it finds. It can also write suppression rules. Every tool is in the MCP tools reference.

Issues are the middle of the loop, not the end of it:

  • Alerts. Fixter’s detectors alert on error bursts without any rule from you, and you can write rules of your own on the same signals.
  • Investigations. The brief on an issue is the same capability that works your Slack alerts, pointed at an issue instead of a thread. See Investigations.