Skip to content

Errors for AI agents

View Markdown

The error model

Honeybadger groups error occurrences by fingerprint: a fault is one unique error within a project, and each occurrence of it is a notice. A fault carries the error class, message, component/action, environment, tags, and an optional assignee; its notices carry the occurrence details (backtrace, request, params, context, session, hostname, revision).

Occurrences are also emitted as notice events on the project’s internal Insights stream, so error data is queryable with BadgerQL too (see the queries instructions — Streams).

Lifecycle and states

  • Unresolved — the default state; the error is open.
  • Resolved — marked fixed. If the error occurs again it automatically REOPENS (resolved is cleared) and a notification is sent — resolving is not permanent suppression. By default a deploy also auto-resolves every open error in its environment (resolve_errors_on_deploy, on by default, per-project) — which is why created.after:"last deploy" is the idiomatic “new errors” triage window.
  • Ignored — new occurrences are DISCARDED (not recorded as notices) and never notify, until unignored. The fault and its existing history remain.
  • Paused — notifications are snoozed for a duration (hour/day/week) or until the error occurs N more times (10/100/1000). Occurrences ARE still recorded — pausing silences the noise without losing data.
  • Pending resolution — marked to resolve automatically at the next deploy. Processed on every deploy regardless of the auto-resolve setting — the per-fault alternative when project-wide auto-resolve is off.
  • Assigned — a user (by email) owns the fault.

Recording can also be paused outright until a set time — occurrences are discarded during the pause, and the first occurrence after it expires notifies. This is separate from the notification pause above and has no search filter.

The same search string is accepted everywhere errors are filtered: the error list UI, the errors dashboard widget’s query field, and the Data API’s q parameter on the faults endpoints.

Syntax

  • Combine filters with spaces; different keys must all match (AND).
  • REPEATING a key ORs its values: class:NoMethodError class:TypeError matches either. This is the only way to express OR — there is no OR operator.
  • Repeating a negated key excludes every listed value: -environment:staging -environment:development excludes both.
  • Bare terms (no key:) full-text search the error class and message, ANDed with the other filters: stripe class:PaymentError.
  • Negate a filter with a leading -: -is:resolved. Not every key is negatable — see the reference.
  • Quote values containing spaces: message:"undefined method".
  • component#action is shorthand for component:X action:Y: users_controller#show.

Values and wildcards

  • * anywhere in a value is a case-insensitive contains match: context.user.email:*@example.com, request.url:*checkout*.
  • key:* alone is a presence check — any non-empty value: context.user_id:* finds errors with a user attached.
  • Array elements are addressed by index in the key path (params.job.args.0.job_id:123), or matched anywhere in the array with a wildcard value (params.job.args:*Foo*).

Filter reference

  • class — Filter by class. Example: class:value (negatable with -)
  • component — Filter by component. Example: component:value (negatable with -)
  • action — Filter by action. Example: action:value (negatable with -)
  • environment — Filter by environment. Example: environment:value (negatable with -)
  • is:assigned — Errors that are assigned. Example: is:assigned (negatable with -)
  • is:ignored — Errors that are ignored. Example: is:ignored (negatable with -)
  • is:resolved — Errors that are resolved. Example: is:resolved (negatable with -)
  • is:paused — Errors that are paused. Example: is:paused (negatable with -)
  • is:pending_resolution — Errors that are pending_resolution. Example: is:pending_resolution (negatable with -)
  • has:ticket — Errors that have ticket. Example: has:ticket (negatable with -)
  • has:tickets — Errors that have tickets. Example: has:tickets (negatable with -)
  • has:comment — Errors that have comment. Example: has:comment (negatable with -)
  • has:comments — Errors that have comments. Example: has:comments (negatable with -)
  • tag — Filter by tag. Example: tag:"foo" (negatable with -)
  • assignee — Filter by assignee email; also accepts assignee:anybody, assignee:nobody, assignee:me (resolved server-side to the current user’s email). Example: assignee:user@example.com
  • created — Lucene-style range on first-seen date. Example: created:[NOW-1DAY TO NOW] (negatable with -)
  • created.before — First seen before a date. Example: created.before:"24 hours ago" (negatable with -)
  • created.after — First seen after a date. Example: created.after:"last deploy" (negatable with -)
  • last_occurred.before — Last occurred before a date. Example: last_occurred.before:"1 hour ago"
  • last_occurred.after — Last occurred after a date. Example: last_occurred.after:"1 week ago"
  • occurred — Lucene-style range on any occurrence date. Example: occurred:[NOW-1DAY TO NOW] (negatable with -)
  • message — Filter notices by error message text. Example: message:"undefined method" (negatable with -)
  • file — Filter notices by file path. Example: file:app/models/user.rb (negatable with -)
  • hostname — Filter notices by hostname. Example: hostname:web-1 (negatable with -)
  • revision — Filter notices by revision sha. Example: revision:abc123 (negatable with -)
  • request.* — Filter notices by request fields (url, referer, user_agent, etc.). Example: request.url:example.com (negatable with -)
  • params.* — Filter notices by request params. Example: params.user_id:42 (negatable with -)
  • context.* — Filter notices by context fields. Example: context.tenant:foo (negatable with -)
  • session.* — Filter notices by session fields. Example: session.id:abc (negatable with -)

Semantics and traps

  • The default error list excludes resolved and ignored faults. A search for “what’s broken” should include -is:resolved -is:ignored; drop them only when resolved or ignored errors are explicitly wanted.
  • Use is: and has: values exactly as enumerated in the reference (is:resolved, is:ignored, is:assigned, is:paused, is:pending_resolution, has:ticket, has:comment). Do not invent other values.
  • Never invent filter keys. An unrecognized filter does NOT error — the whole token silently becomes a full-text search over class and message, which usually matches nothing. The wildcard prefixes (request.*, params.*, context.*, session.*) accept any subkey, but only use subkeys known to exist in the project’s data.
  • assignee: takes an email address. assignee:me resolves server-side to the current user; assignee:anybody and assignee:nobody match presence/absence of an assignee. A bare name (assignee:bob) is never valid.
  • Use class names as given; do not normalize casing (a search for redis is class:redis, not class:Redis).
  • User identity lives in the error context — context.user_id and context.user_email by convention (the tracked field is configurable per project). “Errors affecting user X” → context.user_email:x@example.com; “errors that affected any user” → context.user_id:*.
  • There is NO sort token — sort:count does not exist. Sorting is a separate UI/API parameter (order: recent, frequent), never part of the search string.

Time filters

  • For relative periods, use the .after: forms: last_occurred.after:"24 hours ago" (most recent occurrence), created.after:"1 week ago" (first seen — new errors), occurred.after:"24 hours ago" (any occurrence in the window).
  • For errors that have NOT happened recently, use last_occurred.before: — “errors that haven’t occurred in a month” → last_occurred.before:"1 month ago" (the most recent occurrence is older than a month). Do not reach for a negated .after:last_occurred.* is not negatable, and the unrecognized token silently degrades to a full-text search.
  • Date values are parsed as natural language: "24 hours ago", "today", "july 1", "now", ISO timestamps, and the special value "last deploy".
  • created.after:"last deploy" matches faults first seen since the latest deploy; combined with an environment: filter, “last deploy” resolves to that environment’s latest deploy.
  • Do not add upper bounds that are always true: .before:NOW or [X TO NOW] is redundant for one-sided “since X” ranges — use .after: instead. Use the bracketed Lucene range form (created:[NOW-7DAY TO NOW-1DAY]) only when both bounds are meaningful.