Apify actor error tracking

Know your actor is broken before your users do

Sentinel captures every crash in your Apify actors, groups them into issues, and shows you the exact line that broke along with the breadcrumbs that led there. One wrapper around your actor body is the whole setup.

One wrapper · Node, TypeScript & Python · 2,000 events free · Your data stays private

1 out of 5

“Broken for over a week. Burned through my credits and returned nothing. No reply from the developer.”

Apify Store review · 2 days ago

Without error tracking, this is your monitoring.

The problem

Apify logs die with the run

A failed run writes a stack trace into a log nobody opens. Nothing tells you the same bug hit 1,200 runs, that it started on Tuesday, or that 38 paying customers walked into it. So the first real signal is a refund request, a support message, or a one-star review that stays on your listing forever.

Silent failures

Scheduled runs fail at 3am. Nothing pages you, nothing emails you.

No grouping

One bug across a thousand runs looks like a thousand unrelated logs.

No blast radius

Logs never tell you how many of your users actually hit it.

Issues, not logs

Every crash, grouped into one issue

Exceptions are fingerprinted on the server and collapsed into issues, so a bug hitting a thousand runs is one line on your dashboard, ranked by how much damage it is doing rather than by when it happened.

  • Event count and distinct affected users per issue
  • First seen, last seen, and a 14-day trend so you can spot regressions
  • Fatal, error and warning levels, with handled and unhandled marked
  • Successful-run rate, borrowed from your analytics run totals
  • Resolve or ignore an issue to keep the list honest
Unresolved issues96.4% successful runs
fatalErrorUpstream API 402 Payment Required
src/fetchProfiles.ts › ensureOk1,284 events38 users2m ago
errorTypeErrorCannot read properties of undefined
src/parse.ts › mapUser932 events121 users14m ago
warningTimeoutErrorNavigation timeout of 30000 ms exceeded
src/render.ts › gotoWithRetry488 events29 users1h ago

Thousands of failed runs, collapsed into the handful of bugs causing them.

Root cause

And the exact line that broke it

Open an issue and you get the full stack with source context around the throwing line, plus the breadcrumbs from the seconds before it: the HTTP calls, the navigations, the log lines. You are reading the failure, not reconstructing it.

  • Stack frames with the surrounding source, in-app frames marked
  • The run's input, captured automatically, so you can see what the actor was asked to do
  • Breadcrumb timeline of HTTP, navigation and log events before the throw
  • Apify run context: actor, build, run id, and origin such as SCHEDULER or API
  • Which consumer hit it, so you know whether a paying customer is affected
  • Your own tags and context, attached with setTag and setContext
ensureOk · src/fetchProfiles.ts:57
55 const detail = body?.message ?? response.statusText;
56
57 throw new Error(`Upstream API ${response.status}`);
58}
Run inputcaptured automatically
{ "usernames": ["nasa", "natgeo"],
  "maxItems": 500,
  "proxy": { "useApifyProxy": true } }
Breadcrumbs
0shttpGET /v2/user/followers → 402
5shttpGET /v2/user/by/username → 200
8sapifyActor.main started

Setup

One wrapper. That is the whole setup.

Wrap your actor body once and every future crash reports itself. Your error is re-thrown unchanged, so the actor still fails the way it did before and exits with the same code.

  • Node, TypeScript and Python, both SDKs zero-dependency
  • Installs global crash handlers, so unhandled errors are caught too
  • Re-throws your error untouched: no behaviour change, same exit code
  • Captures the run's input automatically, secrets left encrypted
  • Flushes before the container exits, so nothing is lost on teardown
  • Shares one apifyHub key with analytics: no second key to manage
The whole setup
Node / TypeScript
import { withSentinel } from '@apifyhub/sentinel';

await withSentinel(
  { apifyHubKey: process.env.APIFYHUB_KEY },
  async () => {
    // your actor code, unchanged
  },
);
Python
from apifyhub_sentinel import sentinel

with sentinel(apify_hub_key=os.environ["APIFYHUB_KEY"]):
    ...  # your actor code, unchanged

Add APIFYHUB_KEY as a secret environment variable in the Apify Console, then deploy. The next crash lands on your dashboard.

Why not just read the logs?

Apify Console logs vs Sentinel

Console logsSentinel
Same bug across many runsSeparate logsOne grouped issue
How many users it hitNoDistinct users per issue
When it startedDig through runsFirst seen and 14-day trend
Source around the failing lineStack text onlyYes, with context
The input that triggered itOpen the run to find itAttached to every event
What happened before the throwWhatever you loggedBreadcrumb timeline
Run origin and consumerPartlyAttached to every event
Triage stateNoResolve or ignore
Where you read itPer run in the ConsoleOne dashboard, anywhere

FAQ

Common questions

How do I track errors in an Apify actor?+

Wrap your actor body in withSentinel() from the @apifyhub/sentinel package and add your apifyHub key as a secret environment variable named APIFYHUB_KEY. Any exception thrown by your actor is captured, grouped into an issue, and reported to your dashboard before the process exits. There is nothing else to wire up: no webhooks, no log shipping, no polling the Apify API.

Why are Apify Console logs not enough?+

Console logs are per run. To find out an actor is broken you have to already suspect it, open the right run, and scroll. Nothing groups the same failure across runs, counts how many users hit it, or tells you it started three days ago. Sentinel turns thousands of failed runs into a handful of issues ranked by how much damage each one is doing.

What is an issue, and how are errors grouped?+

Every captured exception is fingerprinted from its type and the top of its stack. Errors sharing a fingerprint collapse into one issue, so a bug hitting 1,200 runs is one line on your dashboard with an event count, a count of distinct affected users, a first-seen and last-seen time, and a trend for the last 14 days.

Will Sentinel change how my actor runs?+

No. The wrapper re-throws your error unchanged after capturing it, so your actor still fails exactly as it did before and still exits with the same code. Reporting happens in the background and is flushed before the container exits.

What context do I get with each error?+

The full stack trace with source context around the throwing line, the input the run was started with, breadcrumbs showing what happened in the seconds before the throw, and the Apify run context: actor, build, run id, origin such as SCHEDULER or API, and which consumer was running it. You can attach your own tags and context too.

Does Sentinel capture the actor's input?+

Yes. The run's INPUT record is fetched once when the SDK initialises and attached to every event from that run, so you can see exactly what the actor was asked to do when it broke. That is usually the fastest way to reproduce a bug: the failing input is right there next to the stack trace. Secret input fields stay encrypted, because only Apify's own getInput() decrypts them, so no plaintext secrets reach the dashboard. Inputs over 16KB are truncated, and you can turn the whole thing off with captureInput: false.

Which languages are supported?+

Node and TypeScript via @apifyhub/sentinel (Node 18+), and Python via apifyhub-sentinel (Python 3.9+). Both are zero-dependency and share one version number, and they compute error fingerprints identically, so the same bug raised from a JS actor and a Python actor groups into a single issue.

What makes this different from a general-purpose error tracker?+

Sentinel is built around Apify's run model. It understands actors, builds, run origins and consumers, it captures the run's input automatically, it ties failures back to the users those failures affected, and it borrows your run totals so it can show a successful-run rate rather than just a raw error count. Setup is one wrapper rather than an SDK you configure yourself.

Is my error data private, and is any of it ever used publicly?+

It is private, and no part of it is ever used publicly. Everything your actors report, including stack traces, captured input, breadcrumbs and the identity of affected consumers, is private to your account. None of it feeds Apify Hub's public pages, and that will never change: the leaderboard, trending and category pages are built only from Apify's own public store data. We do not sell it, publish it, or aggregate it into public benchmarks.

How long is my error data kept?+

Raw events, which is where stack traces, captured input, breadcrumbs and context live, are deleted 90 days after they arrive. That runs as an automatic daily job on every plan, free and paid alike, so nothing older than 90 days is retained. What survives is the aggregate: the issue itself with its event and affected-user counts, plus the per-day totals that draw the trend charts.

What does Sentinel cost?+

Free to start: every account gets 2,000 Sentinel events lifetime. The paid plan is $29 a month and includes 100,000 Sentinel events, metered separately from analytics events, with each extra 100,000 events billed at $5. Raw events are retained for 90 days; issue counts and trends are kept as rollups.

Stop finding out from your reviews.

2,000 Sentinel events free, lifetime. Paid plans include 100,000 Sentinel events per month, metered separately from analytics. Your error data never feeds our public pages.

Need more? Each extra 100,000 events is $5.