Sessions · Plans and data
Troubleshooting
Each problem as you meet it, why it happens, and the fix.
Start with the recorder's state
For recordings, add onChange to the recorder's options, reload the page, and read what it logs in the browser's console. Each line is the recorder's state(): its status, and in upload the last answer from Sessions.
const recorder = createRecorder(init(config), {
// …your options
onChange: (state) => console.log('sessions', state),
});For the journey, run the SDK's command on the server. It sends what waits, or says why it can't:
php artisan mybeast:sessions-flushThe project's setup guide in Sessions shows the same checks, with where your project stands on each.
The recorder logs nothing
start()isn't called, or the page has no config.clientConfig()returnsnullwhile a.envline is missing or malformed: checkMYBEAST_SESSIONS_URL,MYBEAST_SESSIONS_PUBLIC_KEYandMYBEAST_SESSIONS_SIGNING_KEY, and thatMYBEAST_SESSIONS_ENABLEDisn'tfalse. After changing.env, clear a cached config withphp artisan config:clear.- The browser has no
CompressionStream. An old browser records nothing, and your page goes on as before.
If the page fails on the server instead, with an InvalidArgumentException from clientConfig(), the subject or account isn't an id of 1 to 64 letters, digits and . _ : - (an e-mail address isn't one), or the environment's name isn't up to 32 letters, digits, _ and -.
The status stays off
status: 'off' means the token carries no yes: consentAt was null for this person. Check the column you pass, for the account you're signed in as. A token for another project, or one the browser can't read, counts as none too.
status: 'waiting' is the recorder starting. It also waits while this computer's clock is behind the moment of the yes: check the clock, or wait a moment after saying yes.
Uploads get no answer
upload.status: 0 means the browser got no answer at all. Most often the page's origin isn't in the project's Settings → Browser origins, exactly as the address bar shows it, scheme and port included; or the public key is another project's. Otherwise a blocker, or no network. After three chunks in a row with no answer, the recorder stops for that page.
Uploads are refused
401: the token doesn't hold. The signing key isn't this project's, or the token ran out: give the recorder agetToken, or hand on each new token withsetToken().402: the project's subscription has ended. Renew it at id.my-beast.com.403: refused. The answer in the browser's network tab says why:
| refused | Meaning |
|---|---|
not-recording | The token doesn't allow recording: it has no consent_at. |
mask-required | An unmasked token (mask: false) for an environment the project requires masking in. |
monthly-limit | A new recording past the project's recordings this month. A recording already going on goes on. |
erased | The recording was deleted, or its person's or account's recordings erased, while the tab still recorded. |
before-consent | The chunk starts more than 5 seconds before the moment the person said yes. |
For mask-required, take mask: false out of clientConfig(), or record in an environment where masking isn't required. For monthly-limit, see Limits.
Chunks are refused as a leak
422 with refused: leak means a masked chunk still showed an e-mail address, a personal id, an IBAN, or a phone or card number, and kinds says which. The chunk is dropped and the refusal is written in the audit log.
It's most often one of your own UI strings in the dictionary, such as a support address or phone number in a footer. Take it out of the dictionary with uiStrings()'s skip, or mark its element data-mybeast-private.
Everything shows as stars
That's masking with no dictionary: safe, and not broken. Give the recorder your UI strings as its dictionary. A text stays only when it's one of them, so a string your app builds by joining words doesn't match; give the template instead, such as {{count}} open. Digits alone are always masked, and inside a private part every word is. Keep your UI strings readable.
No journey steps arrive
mybeast:sessions-flushsays the SDK is off:MYBEAST_SESSIONS_URLorMYBEAST_SESSIONS_SECRETis missing or malformed.MYBEAST_SESSIONS_JOURNEYisn'ttrue, orMYBEAST_SESSIONS_ENVIRONMENT(orAPP_ENV) isn't up to 32 letters, digits,_and-.- Steps wait for the scheduler: run
php artisan schedule:work, or cron runningschedule:run. - The request is no step: a guest, a JSON read, a prefetch, a route in
journey.skip_routes, or an address no route of thewebgroup answers. What a step is. - Past the month's steps, Sessions refuses the rest as
monthly-limit, and your log says so once.
The key flows don't push
mybeast:sessions-flowsfails with a list of problems: a definition doesn't fit, and every problem is named. What a flow may be.- “No key flows defined”:
journey.flowsdoesn't name your class. - “My Beast sessions is off”: the URL or the server secret is missing. The flows were checked, and nothing was sent.
- A warning that no route is named so: the route doesn't exist in this app, or not in this environment. The flow is still pushed, but that step is never reached until a route has the name.
An erasure throws
ErasureFailed (or ObjectionNotLifted) means Sessions didn't confirm: it was down, the network failed, or it refused the server secret. Nothing is lost if the call runs in a queued job with retries: asking again is safe. A call that returns null wasn't sent at all: the SDK is off or has no server secret.