Reference

Troubleshooting & FAQ

The questions that come up most, and the honest answers.

I don't see any events

Start with pharen verify — it checks the whole chain (key present and well-formed, the right environment for the build configuration, no value truncated by the xcconfig // rule, the config file actually wired, the Info.plist entry present, and whether the key has since been revoked) and names what's wrong instead of leaving you to guess. Add --wait and it will sit and watch for the first event.

If you'd rather check by hand, it's almost always one of three things:

  • The ingest key is missing or a placeholder. If PharenIngestKey isn't set to a real key, the SDK stays completely off — it's the intended way to disable Pharen in local builds. Set a real phi_test_… / phi_live_… value.
  • The purpose isn't granted. Consent is opt-in, so a started SDK with no purposes drops every event. Crashes need telemetry; sessions and track() events need behavioral. Grant them via PharenConsentGrantedAtBuild or at runtime. In a Debug build, the SDK prints a warning at start when nothing is granted — check the console.
  • You're looking at the wrong environment. A Debug build carrying your phi_test_… key lands in development, not live. Confirm which environment you're viewing.

My test crash didn't show up

  • Relaunch the app. Fatal crashes are written at crash time and uploaded on the next launch — the crash won't appear until you reopen the app once.
  • Run on a device, without the debugger. An attached debugger intercepts the signal before Pharen's handler sees it. Launch the app from the home screen, not from Xcode's run button.
  • Check telemetry consent. Without it, crash reports are kept on disk (not discarded) and upload once consent exists — so they may be waiting rather than lost.

Crashes aren't symbolicated

Unsymbolicated crashes mean Pharen doesn't have the build's dSYMs. Upload them — with the fastlane plugin, the Xcode run script, or pharen symbols upload directly — and confirm your Release configuration keeps DEBUG_INFORMATION_FORMAT = dwarf-with-dsym.

Is it safe to re-run an upload or retry?

Yes — always. Symbols deduplicate by debug id (a re-run reports “already present” and exits cleanly). Builds, events, and crashes deduplicate by id on the server, so a retried upload, a relaunch that re-sends a queued event, or a crash report that takes several launches to get through are each counted once. There is nothing to reset between runs.

The CLI printed “using API …”

That's PHAREN_API_URL announcing an active override. It exists only for platform development; unset it to target the default control plane. The notice is deliberate — a stale override should never silently redirect a run.

Where do my key and token come from?

Your organization is created when your application is approved (start with Pharen). After that you issue your own ingest keys: pharen setup ios (or pharen init ios --mint on its own) mints one per environment and writes them into your build settings, so you never handle the value. They're public by design — commit them.

Your control credential is the secret one, and the two must not be confused. pharen auth login signs you in from a browser and stores a session, which is the path to prefer; PHAREN_AUTH_TOKEN is for CI environments. Either way it never belongs in source, and never in a build setting.

Why the split? An ingest key is write-only and ships inside your binary, so it can create data and read none. The control credential can read your data and mint keys, so it stays with the person or the CI job that holds it.

Email from Pharen isn't arriving

Pharen sends from two addresses. Notices about your organization and mail about your own access come from notices@mail.pharen.ai. The email a member can switch on in the console about new reports comes from alerts@notify.pharen.ai. Both show as Pharen, and replies to either go to hello@pharen.ai. If your mail filters quarantine new senders, allow both addresses.

Regaining control of your organization

If no owner of your organization can act for your company — for example, your only owner has left it — write to hello@pharen.ai. We consider a request only with evidence that it comes from your company: proof that you control your company's domain, and an independent confirmation, such as a billing record we hold or a confirmation from an officer of your company. Evidence makes a request one we can consider; it does not by itself decide it.

If owners disagree, we do not choose between them; we may pause changes to your organization's members, credentials and billing while you resolve it, as the Terms provide. Your apps keep sending throughout.

A key leaked — what do I do?

If it's an ingest key, first: that is probably fine. One ships inside every copy of your binary by design, and someone holding it can write junk events into one app in one environment and read nothing. If you want it replaced anyway, pharen ingest-keys rotate mints a replacement and expires the old key after a grace window, so builds already in the field keep working while you ship a new one. pharen ingest-keys revoke --reason compromise is the immediate version — it stops every build carrying that key, right now, and the key is never restored. A revoke without that reason is routine: the builds are held, and an owner can restore the key for thirty days.

If it's your control credential or a query key, treat it as a real leak and revoke it. Full details on all three, and which lever to reach for: Keys & credentials.

My agent's number disagrees with the console

On the same question it cannot: the console and an agent holding a query key read one registry, so a number means one thing on both. When they differ, they are answering different questions. The usual four: a different environment (the environment the key belongs to, not a statement about the build — a developer's local install pointed at the live key reports as live); a different release track (a released count of 0 beside a large unconfirmed count means “cannot tell”, never “no customers”); a different window; or a grouped cell below five that was withheld on one side and not grouped on the other. Ask the agent to state the app, environment, release track and window it used — the request behind every console number is shown on the page, so the two can be compared line for line.

My MCP client cannot send a header

The hosted server authenticates every call with Authorization: Bearer <query key>, and a client with no way to add a header cannot connect yet. The clients that can, with their configuration, are on Connect your agent; if yours is not among them, tell us which one.