> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myrqen.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Things that go wrong in practice, and what to do about each one.

## Known defects

Three things are broken in the product itself rather than in your setup. They are listed
here so you do not spend time debugging them, and each is described honestly rather than
dressed up as intended behaviour.

| What                                                                                                                                                                                                                                  | Status        | Workaround                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ----------------------------------------------------------------------------------- |
| The `myrqen` CLI is not on npm, so `npx myrqen` 404s. `apps/cli/package.json` is `"private": true`.                                                                                                                                   | Not published | [Build from source](/getting-started/installation)                                  |
| `https://api.myrqen.cc` — the CLI's shipped default endpoint — is not deployed. Linking, cloud reports, live progress, and sharing cannot work against it.                                                                            | Not deployed  | [Run your own deployment](/guides/self-host) and `myrqen config set-url`            |
| `myrqen session start` exits 1 with **no local report** when the device is linked, the repository is unbound, and the API is unreachable. `apps/cli/src/session/binding.ts:46` calls `GET /api/v1/workspaces` with no error handling. | Bug           | Set a reachable URL, or scan with `MYRQEN_CONFIG_DIR` pointed at an empty directory |

The third one contradicts the product's own local-first promise, so treat it as a bug to be
fixed rather than a rule to work around.

## Installation

<AccordionGroup>
  <Accordion title="`npx myrqen link` fails with a 404">
    The `myrqen` package is not published to npm — `apps/cli/package.json` carries
    `"private": true`, and `registry.npmjs.org/myrqen` returns 404. Copy elsewhere in the
    repository and on the marketing site that shows `npx myrqen link` describes an intended
    future state, not something you can run.

    Build from source and put the CLI on your `PATH` instead. See
    [Installation](/getting-started/installation#make-myrqen-runnable).
  </Accordion>

  <Accordion title="`myrqen: command not found`">
    A shell alias is not visible to a subprocess, so an agent that shells out will not see
    it. Use the `PATH` shim instead:

    ```bash theme={null}
    mkdir -p ~/.local/bin
    printf '#!/bin/sh\nexec node /path/to/Myrqen/apps/cli/dist/myrqen.mjs "$@"\n' > ~/.local/bin/myrqen
    chmod +x ~/.local/bin/myrqen
    ```
  </Accordion>

  <Accordion title="`apps/cli/dist/myrqen.mjs` does not exist">
    Run `pnpm install && pnpm build` from the repository root. The bundle is produced by the
    CLI package's build step, not by `pnpm install`.
  </Accordion>

  <Accordion title="`/myrqen` is not offered in Claude Code">
    Claude Code derives the slash command from the installed **directory** name, so the
    bundle must be at `~/.claude/skills/myrqen/` or `<repo>/.claude/skills/myrqen/`.

    ```bash theme={null}
    myrqen install
    myrqen doctor      # reports which integrations are present
    ls ~/.claude/skills/myrqen
    ```

    A missing convenience integration does not mean the scanner is broken — `myrqen auto`
    works from any agent with shell access.
  </Accordion>
</AccordionGroup>

## Running a scan

<AccordionGroup>
  <Accordion title="`session start` exits 1 when the API is unreachable — known defect">
    **This is a bug, not intended behaviour.** The product's stated promise is that scanning
    is local-first and never blocked by the cloud, and in this one path it is.

    It triggers when **all three** are true:

    1. the device is linked,
    2. the repository has no existing workspace binding, and
    3. the API is unreachable — which, since the CLI's default endpoint
       `https://api.myrqen.cc` is not deployed, is the normal case today.

    Binding a new repository calls `GET /api/v1/workspaces` at
    `apps/cli/src/session/binding.ts:46`, and that call has no error handling around it, so
    `session start` throws and exits 1 **before any local report exists**. Nothing is
    written; there is no partial result to recover.

    A repository that *already* has a binding is unaffected: `describeExisting` treats the
    stored binding as authoritative and wraps its metadata lookup in a `try`/`catch`.

    Until it is fixed, two workarounds:

    ```bash theme={null}
    # Point the CLI at a deployment that actually answers
    myrqen config set-url http://localhost:3000

    # Or scan with no credential at all, which takes the fully local path
    MYRQEN_CONFIG_DIR=$(mktemp -d) myrqen auto --sync no
    ```

    `--sync no` alone does **not** avoid it: the binding is resolved before the sync question
    is even considered.
  </Accordion>

  <Accordion title="Everything says `needs_review` and nothing is verified">
    That is the honest outcome when the application was not running, or when no agent
    settled the static pass's candidates. Static reading cannot observe a response.

    Start the application, then have the agent verify or refute each candidate:

    ```bash theme={null}
    myrqen --json finding verify MYR-001 --description "…" --location "GET /api/orders/102"
    myrqen --json finding refute MYR-002 --reason "…"
    ```

    See [Findings](/concepts/findings#settling-a-static-candidate).
  </Accordion>

  <Accordion title="A finding submission is rejected (exit code 2)">
    The output names the reason. The usual causes:

    * an extra top-level field, **including `id`** — the schema is `additionalProperties: false`
      and the CLI assigns ids;
    * a secret value that survived redaction;
    * no evidence entries;
    * a length or enum constraint from [the schema](/reference/finding-schema).

    Fix it and resubmit.
  </Accordion>

  <Accordion title="The same issue appears twice in the report">
    A resubmission merges as corroboration only when the summary matches the original word
    for word. To confirm an existing candidate, use `finding verify` — never a resubmission.
  </Accordion>

  <Accordion title="`target authorize --grant` is still refused">
    The origin is quarantined. It appeared only in project content that also tried to
    instruct the scanner, and a human approving a target that injected text authored is not
    meaningful consent.

    If the origin is genuinely part of the project, put it in the project's configuration.
    A new session will pick it up as an ordinary candidate. Do not work around the
    quarantine.
  </Accordion>

  <Accordion title="An action is blocked (exit code 4)">
    Working as designed. Choose a non-destructive validation that demonstrates the same
    property, or record the finding as `strong_evidence` and explain in the report why safe
    validation was not possible. See
    [Authorization and safety](/concepts/authorization-and-safety#the-action-gate).
  </Accordion>

  <Accordion title="`myrqen logout` or `workspace --set` does nothing">
    All three of `logout`, `workspace --set`, and `workspace --detach` are
    confirmation-gated, and confirmations default to **deny** in a non-interactive shell —
    which is what an agent gives them. They print "Left unchanged". Run them in a real
    terminal.
  </Accordion>

  <Accordion title="Docker is installed but hangs">
    Not a problem. Docker is optional and is never a user-facing prerequisite. Myrqen
    reports reduced coverage — "Isolated runtime checks are unavailable on this machine;
    other checks still run" — and carries on. Force that behaviour with
    `MYRQEN_ASSUME_NO_ISOLATION=1`.
  </Accordion>
</AccordionGroup>

## Linking and accounts

<AccordionGroup>
  <Accordion title="`DEVICE_LINK_NOT_APPROVED` (428)">
    Nobody has approved the device in a browser yet. Open the approval URL while signed in
    and press **Approve this device**. Visiting the URL is never approval.
  </Accordion>

  <Accordion title="`DEVICE_LINK_EXPIRED` (410)">
    Link requests live 10 minutes. Run `myrqen link` again.
  </Accordion>

  <Accordion title="`DEVICE_LINK_ALREADY_CONSUMED` (409)">
    The verifier was already exchanged, and it cannot mint a second credential. Start a new
    link request.
  </Accordion>

  <Accordion title="`DEVICE_REVOKED` (401)">
    The credential was revoked in the app. Run `myrqen link` again.
  </Accordion>

  <Accordion title="I lost my password">
    Use a recovery code at `/recover`, together with a new password. Ten codes are shown
    once at signup and that is the only recovery path — no email is ever sent.
  </Accordion>

  <Accordion title="I lost my recovery codes too">
    There is no other recovery path. Local scanning and local reports are unaffected, since
    neither needs an account.
  </Accordion>

  <Accordion title="`/admin` says forbidden even though I am the only account">
    Being first does not make you an administrator. The role is granted **only** to the
    address in `PLATFORM_ADMIN_EMAIL`, and only at signup:
    `apps/web/lib/auth-service.ts` computes
    `isPlatformAdmin = configuredPlatformAdminEmail() === email` and nothing else ever sets
    it. With the variable unset, the deployment has no administrator at all.

    So: set `PLATFORM_ADMIN_EMAIL` **before** signing up, then create that account. An
    account that already exists is not promoted by setting the variable afterwards.

    Some copy elsewhere in the repository says the first account in a fresh deployment
    becomes the platform administrator. That is not what the code does.
  </Accordion>
</AccordionGroup>

## Syncing and sharing

<AccordionGroup>
  <Accordion title="Myrqen never asks whether to sync">
    It does not ask a question that cannot succeed. One of these is true:

    * the device is not linked;
    * the repository is not bound to a workspace;
    * the plan's cloud-report quota is exhausted (`quota_blocked`);
    * `--sync no` was passed;
    * the shell is non-interactive, in which case `cloud.state` is `decision_required` and
      the **agent** is expected to ask you, then run `myrqen session sync-decision yes|no`.

    `myrqen status` shows which.
  </Accordion>

  <Accordion title="`SYNC_DAILY_LIMIT_REACHED` / `SYNC_WEEKLY_LIMIT_REACHED`">
    The scan still runs and still writes a full local report. Quota windows are UTC-anchored:
    the day resets at 06:00 UTC, the week at Monday 06:00 UTC. `details` carries `resetsAt`,
    and `myrqen status` prints the exact instants.

    After the reset:

    ```bash theme={null}
    myrqen reports
    myrqen sync <localReportId>
    ```
  </Accordion>

  <Accordion title="`REPORT_EXPIRED` (410)">
    The report passed its retention window, so its body and stored object were deleted and
    its share links stopped working. Retention is 21 days on free, 180 on pro, 365 on team.

    Your local files under `.myrqen/reports/` are untouched — reopen the HTML.
  </Accordion>

  <Accordion title="I lost a share URL">
    Plaintext slugs are not stored, only a hash, so an existing link cannot be re-listed.
    Create a new share and copy the URL this time.
  </Accordion>

  <Accordion title="A recipient sees nothing, or too little">
    Check the principal rules. A viewer with no matching rule gets the share's **default**
    policy, and if that policy allows no findings they see a report with no findings. The
    dashboard's share panel previews exactly what each recipient receives before you create
    the link.
  </Accordion>

  <Accordion title="`RATE_LIMITED` on a share link">
    Too many incorrect passwords for that link — 10 attempts per 10 minutes. Wait, then
    confirm the password with the report owner. Correct attempts are not counted, so this is
    not a lockout of legitimate readers.
  </Accordion>
</AccordionGroup>

## Self-hosting

<AccordionGroup>
  <Accordion title="`DATABASE_URL is not configured`">
    Copy `.env.example` to `.env` at the **repository root** and set it. In production the
    root `.env` is deliberately not loaded, so the variable must be a real environment
    variable.
  </Accordion>

  <Accordion title="`APP_BASE_URL is not configured` in production">
    Required under `NODE_ENV=production`. Share links and session-cookie security are both
    derived from it, so a localhost fallback would hand out links nobody can open and
    cookies without `Secure`.
  </Accordion>

  <Accordion title="Object storage refuses to start in production">
    The `filesystem` driver is refused under `NODE_ENV=production`, because report bodies
    would live on one container's disk — lost on the next deploy and invisible to other
    replicas. Set `OBJECT_STORAGE_DRIVER=s3`, or
    `OBJECT_STORAGE_ALLOW_EPHEMERAL=true` for a throwaway production-mode run.
  </Accordion>

  <Accordion title="Stored reports stopped opening after a key rotation">
    Move the old key to `REPORT_ENCRYPTION_KEY_PREVIOUS`, which accepts retired keys for
    reads. Without that, nothing encrypted under the old key can be decrypted.
  </Accordion>

  <Accordion title="`/api/v1/ready` returns 503">
    The response names every dependency it probed — database, event bus, object storage,
    encryption keyring — with a `detail` for the failing one. Gate traffic on `ready` and
    container restarts on `health`, never the reverse.
  </Accordion>

  <Accordion title="Rate limits behave as though there were none">
    `TRUSTED_PROXY_HOPS` is unset, so there is no trustworthy client address and every
    request shares one bucket. Set it to the number of proxies in front of the app —
    Railway and most single-proxy platforms need `1`.

    Separately, without `REDIS_URL` counters are process-local, so N replicas allow N times
    each limit.
  </Accordion>

  <Accordion title="The app refuses to start after adding Polar variables">
    All four of `POLAR_ACCESS_TOKEN`, `POLAR_ENVIRONMENT`, `POLAR_WEBHOOK_SECRET`, and
    `POLAR_PRODUCTS` are required together. A half-configured payment path takes money and
    grants nothing, so it is refused outright.
  </Accordion>

  <Accordion title="The benchmark reports a missed finding">
    Most often the demonstration patch is still applied. Revert it and restart the fixture:

    ```bash theme={null}
    node scripts/demo-fix.mjs --revert
    ```
  </Accordion>
</AccordionGroup>

## Getting more detail

```bash theme={null}
myrqen doctor                 # what this machine and agent setup can assess
myrqen --json session context # the authoritative session state
myrqen status                 # account, device, and quota
cat .myrqen/sessions/*/session.json
```

`doctor` reports capability, not alarm: `info` is a missing convenience, and `attention` is
reserved for something that actually blocks the product.
