Menu

Choose a theme and configure high-contrast mode. Preferences are saved in your browser only.

User preferences

Theme

Pick a palette or follow your system preference.

High contrast

Sharper text and borders. System follows your OS setting.

Copy page

Operations and limits

Run your Bicho installation on Cloudflare. Learn about storage, quotas, access controls, and background enrichment, and troubleshoot missing error reports.

You operate Bicho’s Worker, D1 database, private R2 bucket, and credentials in your Cloudflare account. Cloudflare account and platform limits apply in addition to the application’s quotas and payload limits. Bicho does not set a hosting price or guarantee that a workload fits a free allowance.

Local and hosted resources

Follow the setup guide for provisioning, migrations, deployment, and project registration. The core’s wrangler.jsonc binds D1 as DB and R2 as PAYLOADS, enables nodejs_compat, and declares an hourly Cron Trigger at 0 * * * * (UTC). Preserve those binding names when choosing your resource names.

Local development uses local storage, not the hosted database or bucket. Apply migrations and register projects in the environment you intend to test. Generating offline project SQL or editing a project example registers nothing until that SQL is applied. Local success does not establish hosted credentials, resource bindings, scheduled delivery, or project registration.

Use a Worker secret for hosted BICHO_ADMIN_TOKEN. An absent or empty value makes admin routes fail closed with 503, not 401. Local development supplies its own token separately. Never reset a populated D1 database to reapply the initial migration: editing an already applied migration does not upgrade it.

Quotas, cost, and storage growth

Projects default to 1000 new events per UTC hour. At registration, hourly_limit accepts an integer from 1 through 1000000. D1 enforces the limit atomically, including concurrent requests. Usage follows receipt time, not a client-supplied occurrence timestamp.

Already stored occurrence UIDs do not consume quota. Distinct occurrences grouped into one issue do consume it. A whole-request quota rejection returns 429 with Retry-After until the next UTC hour; exhaustion after an accepted batch prefix returns HTTP 200 with protocol-specific rejection details instead. See OTLP responses and retries and Sentry responses.

Quotas cap accepted events, not incoming requests or total Worker cost. Invalid requests, duplicates, administrative queries, map uploads, background processing, and storage operations still use platform resources. Check Workers limits, D1 limits, and R2 limits against your account and workload.

D1 stores project configuration, issue/event metadata, searchable tags, source-map registrations, processing state, and issue-status history. R2 stores gzip-compressed captured evidence, uploaded maps, and separate derived enrichment objects. Compression is not a retention policy.

Events are append-only. Resolving, ignoring, muting, or reopening changes an issue’s status, not its captured events or payloads. New occurrences do not automatically reopen resolved, ignored, or muted issues. There are no event/issue DELETE endpoints, retention deletion, or operator cleanup/restore jobs in the core.

R2 is written before the D1 index. An ambiguous index failure can leave an unreferenced object; Bicho retains it rather than risk deleting committed evidence. Known duplicate uploads can be removed, but that is not general garbage collection. Budget for captured events, maps, derived objects, and retained unreferenced uploads. Configure backups, recovery procedures, and capacity monitoring for both D1 and R2 yourself. Avoid bucket lifecycle rules that delete payloads still referenced by D1.

Abuse protection and CORS

Numeric project IDs and browser ingest keys are public, not bot protection. Configure Cloudflare WAF and rate limiting rules on your production custom domain for /v1/logs, /api/, and /mcp as appropriate. Available controls depend on your Cloudflare plan; the repository does not create these rules.

Avoid interactive challenges on these paths. SDKs, exporters, API clients, and MCP clients cannot complete them. Tune limits for legitimate error bursts and users sharing an IP. Disable unused workers.dev and preview URLs so traffic cannot bypass domain-level rules. The default manifest enables workers.dev and disables preview URLs.

Ingest supports browser preflight and any origin, but still validates the ingest key and any required secret. API CORS uses CORS_ORIGINS; MCP also rejects unexpected or opaque origins and permits same-origin requests. CORS is not authentication and cannot stop a non-browser client from using exposed credentials. Keep dashboard admin credentials on the server. See privacy and credentials.

Background enrichment and capacity

Ingestion indexes events immediately. Successful ingestion and source-map uploads also request background enrichment through ctx.waitUntil(). This is best-effort work, not a durable queue. The hourly Cron Trigger recovers interrupted work and continues eligible batches.

A D1 lease permits one processor at a time, with a one-minute cooldown and recovery after five minutes. A request during cooldown does not arm a timer for the next minute; the next eligible request or cron invocation must continue the work. Each run processes at most 25 events and 100 source-map lookups. Large events save a frame cursor for a later run. With no traffic, a backlog advances by at most one batch per hour, and some events need multiple runs.

Missing maps wait for an upload in their project rather than being rescanned each hour. Uploads invalidate pending continuation across that project, including unrelated builds, so continual uploads can delay progress. Upload maps before their events when possible. Retryable storage failures back off for one hour and stop after three attempts. Permanent invalid evidence and exhausted failures remain visible; there is no public retry/reset endpoint.

Enrichment writes separate derived evidence. It never changes original event bytes, grouping fingerprints, or issue status. Bicho does not inject debug IDs, fetch remote maps, or discover sourceMappingURL. See source maps for supported references, positions, map limits, and incomplete-result reasons.

Monitoring

Inspect authenticated GET /api/:project_id/processing or MCP get_processing_health. Project status counts and global processor health have different scopes. Global processed and failed describe attempts in the last run, not lifetime totals. An idle invocation leaves health unchanged.

A pending event may be waiting for a map or resuming budget-limited work. not_applicable is normal when there is no usable source-map reference. Zero pending/failed events does not prove the Cron Trigger has fired. Check the deployed trigger and scheduled invocation logs separately, and inspect event enrichment reasons, context-missing indicators, and truncation flags.

Monitor ingestion 429/5xx rates, partial-success rejection counts, Worker error logs, D1 query/storage usage, R2 growth, and enrichment backlog. A 200-only success metric misses OTLP and Sentry partial rejections. Responses include a server-generated X-Request-ID; internal failure logs include request IDs and error names rather than credentials, query strings, or captured bodies. Preserve the request ID when diagnosing a failure without logging sensitive request headers or payloads yourself.

Troubleshoot missing events

For Sentry SDKs, use the generated Bicho DSN and remove any old tunnel or custom transport destination. Secret-enabled backend projects also need sentry.headers. Disable unsupported integrations, flush before shutdown, and check accepted, rejected, and discarded in the response: an SDK may ignore partial rejection. Follow Sentry delivery checks, then search the stored evidence as described below.

For OTLP exporters:

  1. Confirm the exporter targets this instance’s /v1/logs with HTTP JSON or protobuf. A redirect, HTML challenge, gRPC connection, trace exporter, or wrong environment is not a successful logs delivery.
  2. Verify the project was registered in this environment, and use the generated ingest headers. Add the secret only for a backend project that requires it. Admin bearer tokens do not substitute for ingest credentials.
  3. Confirm your logs instrumentation actually emitted an exception record or numeric ERROR/FATAL log. Exporter environment variables do not install capture. Flush before shutdown and inspect the full OTLP response for partial rejection.
  4. Check request/batch limits, 429/5xx responses, and Retry-After. Preserve occurrence UIDs during transient retries. A fixed test UID represents one occurrence regardless of how often you resend it.
  5. Search the correct project with status=all for issues. Issue lists default to unresolved, and new events do not reopen hidden issues. Remove environment, release, tag, and time filters before concluding evidence is absent. Statistics default to the last 24 hours; they are not an unbounded event count.
  6. Read the stored event through the API or MCP. OTLP correlation IDs and occurrence UIDs are not the server’s event lookup ID. Sentry event_id values become the event lookup ID, normalized to lowercase hexadecimal without hyphens. Missing enrichment does not mean ingestion failed.

For a map problem, check the project and debug ID, matching captured references, positive one-based line/column coordinates, supported map structure, and event-specific reasons. A release label alone is insufficient. Follow source-map troubleshooting rather than repeatedly resending the event.

For MCP connection failures, use the installation’s /mcp, not the public website’s documentation MCP. Supply the admin bearer header, initialize with a Streamable HTTP client, and send Content-Type: application/json plus Accept: application/json, text/event-stream. Check proxy forwarding and Origin rules. GET is not unauthenticated discovery, and OAuth is not implemented.

Response status checks

HTTP status Concrete checks
400 Validate IDs, query filters/cursor scope, known OTLP fields, map structure, issue-status body, or MCP protocol input.
401 Check the admin bearer header and configured token. Ingest credentials cannot authorize admin routes.
403 Check ingest key/secret pairing or MCP Origin. Also distinguish an edge WAF response from the Worker’s response.
404 Check the deployment, project ID, and resource within that project.
405 Check the method. MCP requires POST; event/issue DELETE is unsupported.
406 For MCP, accept both JSON and event-stream media types.
409 Different map content already uses this immutable project/debug ID. Use the correct build’s ID.
413 Reduce request bytes, decoded size, batch size, or the applicable stored-output limit.
415 Check content type and compression. MCP requires JSON; OTLP requires JSON or binary protobuf.
429 The project’s UTC-hour accepted-event quota is full. Honor Retry-After. Edge rate limits may also return 429.
500 Check Worker error logs and D1/R2 availability for internal read/storage or processing failures.
503 Check ingest storage availability, the admin secret, or a D1-indexed payload missing from R2, depending on the route.

OTLP errors and MCP JSON-RPC errors differ from REST’s { "error": "..." } response. Diagnose the route and response body, not just the status code.

Unsupported modes

Bicho has no built-in dashboard, general log archive, traces, metrics, attachments, session replay, alerts, native crash symbolication, automatic reopening, or retention deletion. Source maps must be uploaded; remote source fetching, indexed/sectioned maps, and artifact bundles are unsupported. A separate dashboard can use the authenticated API, but it must not publish the admin token in browser code.

Type to search the documentation.