Skip to content

Diagnostics and recovery

Start with the operation receipt

In Settings > GitHub evidence, inspect a repository's coverage and open its refresh receipt, or use Connections > Refresh history. Copy the refresh reference before investigating or retrying. Expand a repository's Collection diagnostics to see requests started, list pages read, elapsed time, and each evidence category's completion or stopping reason. The same diagnostics are available through github_refresh_get in the CLI and MCP. Older receipts return diagnostics: null; missing counters do not mean no requests occurred.

Requests count calls actually started, including failed calls. List pages count successfully parsed list responses, including pages subsequently rejected for inconsistent totals or pagination. Repository metadata and branch-head reads are requests, not list pages. Counters describe the recorded collection attempt, not all earlier retries. Elapsed time includes network waiting and is not CPU time. Diagnostics are kept in refresh results, separate from observation equality, so timing variation does not create Activity changes.

New refresh receipts also record bounded change categories against the previous accepted source observation. Comparison happens in the accepting database batch before that observation is replaced. A first observation, unchanged evidence, and a missing legacy comparison are different states. Completion summaries distinguish access/feature coverage gaps from credential rejection, runtime failures, and collection bounds; a fully collected result can still contain failing CI or security findings. Activity entries retain source attribution when the linked receipt expires. The receipt and Activity read contracts share workspace authorization across browser, CLI, and MCP.

API failures include a server-generated support reference. Browser and CLI messages preserve it; hosted MCP command failures include error.reference. HTTP API errors also carry X-HQ-Support-Reference. A reference identifies a failed request, not proof that a write was rolled back. Inspect durable receipts or saved revisions before retrying an interrupted operation, and reuse the same refresh/event ID when its acceptance is uncertain.

Disabled sources, missing credentials, provider cooldowns, stale evidence, and overdue scheduling are distinct states. Schedule warnings use the workspace snapshot's server time and allow for bounded queue draining. A delay warning is a prompt to inspect progress, not proof that the collector is stuck. Browser closure does not stop hosted collection.

Find the corresponding logs

Inspect the exact serving Worker with Cloudflare Fleet first. In Workers Observability, enumerate available fields, then filter the relevant time window by the Worker and one of these application fields:

Application eventCorrelation and interpretation
hq.request.failedreference, bounded operation, HTTP status, safe classification, and elapsed time
hq.github.repository.startedrefreshId, repositoryId, sourceId, workspaceId, and server-generated runId identify the claimed attempt
hq.github.repository.completedThe same identities plus collection status, receiptRecorded, evidenceStored, capacityLimited, and diagnostic counters; incomplete collection can occur inside an otherwise successful Worker invocation
hq.github.batch.completedrunId, scheduled/background trigger, processed count, elapsed time, and stop reason
hq.push.interruptedPending workspace notifications were retained for retry; the warning contains no record bodies, identities, or exception text. Check the Durable Object binding, D1 outbox and scheduled repair before assuming an open socket is up to date
hq.secrets.cleanup.interruptedExpired encrypted input may remain in private staging; inspect scheduled maintenance and D1 recovery. Input expiry still prohibits use, and collection is attempted independently

Each event has schemaVersion: 1. Correlate the event's platform invocation ID with Workers CPU/wall-time measurements and available database metrics. Application elapsed time cannot substitute for platform CPU. A repository start without a matching completion can indicate interruption; inspect invocation outcomes and the durable receipt before concluding why. Abrupt CPU or process termination can prevent final logs entirely. A scheduled batch summary includes recovery, scheduling, collection, and final recovery; setup failures produce a failed summary with no processed items. item_limit means the configured slice was consumed, not proof that a backlog remains. time_limit can mean insufficient time to safely start another repository, even before the wall deadline. drained means no eligible item was found; cooldowns, an existing claim, or disabled authority can still leave queued work.

Application logs accept only a typed, runtime-validated field allowlist. They omit tokens, credential references/digests, authorization and cookie headers, request/response bodies, repository names, provider URLs, branch names, commit messages, raw exceptions, and stack traces. Unexpected runtime/network errors are not mislabeled as request-limit failures. Do not paste raw platform log records into Activity or support messages; use the reference, fixed classification, and relevant counters. Diagnostic logging failure must never change whether an operation is accepted.

Recovery by outcome

  • Permission or feature unavailable: review the selected repository and existing read-only grant; do not infer a clean scan or broaden permissions automatically
  • Credential rejected or configuration invalid: an owner must repair the configuration using the protected secret boundary and documented rotation sequence
  • Provider cooldown: honor the persisted retry deadline shared by identical credentials; repeated manual retries do not bypass it
  • Page/request limit: counts are lower bounds; inspect workload and capacity policy before increasing the bound
  • Response-size, malformed response, or invalid pagination: preserve the safety boundary and diagnose the provider response in an appropriately protected environment
  • Timeout, interruption, or unexpected failure: inspect the correlated invocation and receipt, then allow leased work to recover or explicitly retry terminal work
  • Overdue scheduling: verify the exact deployed handler and Cron configuration, credentials, source eligibility, and batch diagnostics before changing cadence

Do not restore an older passing observation merely to clear an error. Follow the GitHub recovery contract and preserve source revisions, authorization checks, leases, attempt limits, and credential cooldowns.

Cloudflare Free-plan compatibility

Official limits verified on 2026-09-06. Successful operation on Paid does not establish Free compatibility.

The read-only github_coverage projection adds bounded local D1 reads and response serialization only while its rows are visible. Its statement-count regression is independent of selected repository count and includes live authorization and revision rechecks. Source fanout and UTF-8 response limits reject oversized selections with an exact-connection fallback. These bounds do not measure billable rows, platform CPU or total observer traffic, so they do not establish Free compatibility. Coverage navigation adds no GitHub calls or background collection and does not relax the recorded Paid requirements below.

Overview's workspace_attention projection adds no provider calls. Each selected attention_connection read invokes two bounded Hookrelay operations or three bounded Endpoint Monitor operations, plus authorized local metadata reads. The browser selects at most two operational connections and does not poll them on an interval. Provider paging limits remain visible, responses are capped at 256 KiB, and explicit resource context is capped at 1,000 association rows. These application bounds are not measured platform CPU, total downstream database work or a spending ceiling; repeated manual reads and multiple observers still consume resources. No additional Free-plan exceedance or verified Free compatibility is established by this feature.

Feature or operationFree constraintEvidence and consequence
Scheduled GitHub collectionWorkers CPU: 10 ms per invocation on Free; the minute Cron receives 30 seconds on PaidHosted single-repository collection on 2026-09-06 recorded approximately 23-42 ms CPU, including a diagnostic scheduled pilot at 42 ms CPU and 4.18 seconds wall time. This is an observed Free allowance exceedance, not a fleet worst-case estimate. Sustained overruns can terminate invocations and exhaust recovery attempts
Scheduled GitHub external readsFree: 50 external subrequests per invocation; Paid default: 10,000The twenty-repository slice projects 140 requests for single-page complete collections and caps fully paginated collections at 540. A local Workers fixture executes the full 540-call slice successfully. Both workloads exceed Free; the smaller single-repository HTTP slice does not by itself establish CPU or database compatibility
Scheduled GitHub database workD1: 50 queries per Worker invocation on Free; 1,000 on PaidA fifty-repository local D1 fixture on 2026-09-06 executes approximately 90-180 SQL statements per scheduled slice, counting every batch statement separately. Those slices exceed the documented Free query allowance and stay below Paid's allowance. An idle tick in the same fixture executes eight statements and no GitHub requests. These are application statement counts, not a measurement of Cloudflare binding subrequests, billable rows, or CPU
Stored application/invocation logsFree: 200,000 events per day and 3-day retention; Paid: 20 million included per month and 7-day retentionAt the target workload of fifty repositories refreshed every five minutes, two repository events per attempt plus one batch and one invocation event per minute project about 32,000 events per day before HTTP traffic, retries, other Workers, or future tracing. This logging projection alone fits Free; account-wide usage is separate
GitHub refresh receiptsApplication retention is independent of platform logsCompleted historical receipts expire after the application's retention window except the source's latest receipt. References can outlive the corresponding platform logs; neither store is a permanent forensic archive

Workers CPU, external/internal subrequests, D1 per-invocation queries and daily/monthly row allowances, GitHub rate limits, and logging quotas are independent. Fleet-wide daily D1 row reads/writes have not been measured by the statement-count fixture; a query can touch many rows and indexes. The scheduler's request cap alone does not establish Free support. Disabling scheduled collection and leaving GitHub sources disabled is a supported way to avoid background GitHub usage, at the cost of missing or stale evidence; it is not proof that the rest of the application meets every Free limit. No verified Free-compatible live collection configuration is claimed by the pilot. A Paid-to-Free downgrade requires that fallback or a separately verified collector redesign, not just a smaller external-request batch.

The checked-in and release-artifact Wrangler configurations limit every invocation to 2,000 ms CPU and 1,000 total subrequests. Workers Observability for the seven days ending 2026-09-07 recorded a scheduled CPU maximum of approximately 403 ms, leaving about five times the observed peak. The subrequest ceiling leaves headroom above the application's fully paginated 540-request scheduled slice while reducing the Workers Paid default of 10,000. Cloudflare terminates an invocation that exhausts either ceiling; the durable job and lease records remain the recovery authority, and a resource-limit outcome must be correlated before retrying or raising a bound.

Custom limits.cpu_ms and limits.subrequests require Workers Standard. A Free-oriented fork must omit the custom block and rely on the fixed Free ceilings of 10 ms CPU, 50 external subrequests, and 1,000 internal-service subrequests. That fallback does not make scheduled collection compatible: the observed CPU and documented 140 to 540 external-request slice remain Free exceedances, so scheduled collection and its sources must stay disabled unless a separately measured design is introduced. The execution-ceiling behavior and fixed Free limits were verified against Workers limits and Wrangler limits configuration on 2026-09-07.

Structured logs use the existing enabled Workers Observability configuration. This feature does not enable tracing, Logpush, exports, or an external logging service. API successes do not emit extra application logs. Store queries and retention are operator concerns, not a raw-log API exposed to workspace users. Retention and quota changes require an explicit update to this compatibility record.

Workspace push adds transactionally recorded notifications, membership checks, and delivery acknowledgements to this collector baseline. The scheduled regression fixture keeps these application statements below its bounded Paid budget; the idle path adds one pending-outbox query. Trigger writes also consume D1 row-write allowance and are not represented by application statement counts. These changes do not establish Free compatibility or remove the existing Free exceedances.

GitHub Activity summaries add a bounded repository-result read when a refresh finishes. Per-repository change comparison runs within an existing accepting statement, and receipt links do not increase GitHub API calls or add source-inventory reads to the Activity view. These costs remain covered by the scheduled statement-budget regression; they do not remove the recorded Free-plan exceedances. Opening a receipt explicitly reads its source's bounded history and selected result, independently of the Activity live-update subscription.

Repository-attributed GitHub events add a conditional association insert per audit batch, bounded by that run's repository selection. These retained links and their notification triggers consume D1 writes even after a receipt is pruned; unchanged scheduled runs still create no journal event or association rows. The repository overview's repository_context command reads bounded local association metadata and exact totals, without provider requests or credential resolution. Its small activity_feed query is separate from metadata invalidation, and neither runs while another repository section is mounted. Counts and JSON membership scans still consume CPU and D1 row work; these changes do not establish Free compatibility or remove the collector's documented exceedances.

Sources: Workers limits, Workers Logs, Workers pricing, and D1 limits.

Reviewed bulk expectations use local HQ metadata only, with no provider requests or polling. EXPECTATION_BULK_LIMITS bounds repository selection, request and saved review bytes, live unapplied reviews per actor, and expired-plan cleanup. The SQL uses JSON selections rather than expanding one bound parameter per field and repository. Apply is a fixed-size batch of statements, but affected repository rows, immutable Activity links, transfer clocks and push triggers still consume D1 row writes. Applied plans and operation receipts are retained; expired unapplied plan cleanup is bounded. These costs are not a spending ceiling and do not establish Free-plan CPU compatibility or remove the collector's documented Free exceedances. An interrupted response should be investigated through the original expectation review and receipt, not repeated batches with new IDs.

Reviewed project organization follows the same local-only cost boundary. PROJECT_ORGANIZATION_LIMITS bounds selected assignments, used target projects, serialized inputs/reviews, pending reviews and cleanup. Apply can create projects, update selected project presentation fields and change selected repository associations in one atomic receipt-bound batch. It captures Activity against both affected project identities without rewriting prior history. Fixed statement counts do not make the associated D1 row writes, structural clocks or push triggers free, and no Free-plan CPU claim is implied. Inspect the original organization review after an interrupted response instead of issuing new batches.

On-demand release and deployment reads add at most one fixed GraphQL query and one immutable-SHA REST comparison per uncached collection. Pull-request and issue context adds at most two fixed GraphQL queries for bounded metadata and exact sampled PR signals. Neither changes scheduled GitHub work. Each per-enrolled-pair context cache lasts five minutes, and a shared credential-hash budget admits at most ten contextual collections per minute across both features. Cache leases, budget counters, acceptance and source notifications consume D1 reads/writes even though the provider operation is read-only. The bounded response parser and serialization also consume Worker CPU. These application caps are not platform CPU or billable-row measurements and do not establish Free compatibility or remove the scheduled collector's recorded exceedances. They use the existing Paid profile without new bindings, credentials, logging configuration or execution-limit changes.

On-demand fleet discovery and reviewed enrollment share the Work/Releases credential budget and cooldowns. Discovery uses one fixed GraphQL query per uncached page; review verification uses at most two within a shared deadline. The latest source cache is byte-bounded, and the HQ comparison scans only the bounded workspace inventory. Apply performs a fixed-size atomic HQ batch with no provider writes, but selected rows, identity bindings, receipts, immutable Activity links, structural clocks and push triggers consume D1 writes. Pending-plan and cleanup limits do not limit retained applied history. These are application bounds, not measured platform CPU or billable-row totals, and establish no additional Free compatibility or relaxation of the documented Paid requirements. API failures use the existing support-reference logs; successful discovery does not add raw provider bodies or credential identities to logs.

Repository operational checks use COVERAGE_LIMITS for a bounded provider read and an independently limited shared workspace budget. Accepted reads retain only minimized evidence and publish changed observation records. Cache leases, budgets, invalidation triggers and acceptance checks consume HQ D1 work even though the provider operation is read-only; the provider's own service and database work are additional costs. Subscription paging or resource bounds can leave coverage incomplete, and excess connection fanout fails before provider work. The browser performs no timed coverage polling and fleet assessment makes no per-repository provider calls. These logical limits are not measured platform CPU, billable rows or a global spending ceiling, and establish no additional Free compatibility or relaxation of the documented Paid requirements. No new bindings, credential scopes, log sinks or invocation ceilings are introduced.

Linked Hookrelay checks can consume up to eight subscription pages per connection, within the same twelve-call budget shared with Monitoring. The inventory read is reused for every selected linked subscription on that connection. It stops at the first complete page sequence, a disappeared entry, the page ceiling, total call budget or elapsed allowance. A larger page allowance permits deeper inventory verification; it does not raise the total provider-call or workspace-check budget. Compared with the former two-page allowance, an admitted check can do more parsing and authorization work in HQ and more subscription metadata reads in Hookrelay. Neither page count nor the retained result size measures that downstream work, and Free-plan CPU, KV and D1 compatibility remain unverified. An incomplete inventory cannot establish a unique name match or prove a subscription is missing; inspect the paginated Hooks workspace when a repository check remains limited.

Hosted capacity verification

On 2026-09-06 an owner-approved hosted fleet of approximately fifty active repositories completed two unattended sweeps using the bounded Paid profile. Each sweep made 307 GitHub requests, with the full queue draining in approximately two minutes. Every repository had one attempt per sweep. Incomplete results reflected unavailable repository or endpoint access, not timeouts, rate limits, request/page bounds, or storage capacity. These observations describe that selected scope and provider state; they are not a guarantee for arbitrary repositories or deeper pagination.

A correlated twenty-repository scheduled invocation used 354 ms CPU and 30.09 seconds wall time; a nine-repository invocation used 129 ms CPU and 10.36 seconds wall time. An idle scheduled sample used 5 ms CPU. These are invocation samples, not a measured total CPU cost for an entire sweep. Some invocation and console rows were absent from the inspected log query; stored receipts established complete repository coverage, and no lossless-log or full-window health claim is made from those queries.

At that observed request count, twelve sweeps per hour project approximately 3,700 GitHub requests per hour before manual refreshes or other applications using the same quota. This is a projection from two sweeps, not measured hourly traffic. The observed repeat began approximately six minutes after the first: a five-minute source interval determines eligibility, and the minute scheduler can add a tick's waiting time. Browser polling does not drive collection or reset that eligibility.