IrisBooks Manual
Chapters
Manual / Troubleshooting
Chapter 10

Troubleshooting

Common situations and how to clear them. When in doubt, run iris validate — it’s the fastest way to learn what’s wrong.

iris validate reports errors

iris validate checks every file and prints what’s wrong. The usual causes:

  • Unbalanced entry — debits don’t equal credits. Fix the amounts so they sum to the same total.
  • Unknown account — a journal references an account not in config/chart-of-accounts.yaml. Add the account to the chart (or use an alias). Don’t invent account paths inside the journal.
  • Date mismatch — the date: field doesn’t match the YYYY-MM-DD prefix of the filename. Make them agree.
  • Bad statusstatus must be draft or posted.
  • YAML won’t parse — usually indentation or a stray colon in the frontmatter. The error names the file.
  • Tax classification (JP taxable books) — a tax block with an unknown category, or a rate that doesn’t match its category (e.g. a taxable_sale with no rate, or an export_sale with a non-zero rate).

Fix and re-run. Your AI assistant can do this loop for you.

”I posted an entry but it’s not in my reports”

Reports include only posted entries. If a transaction is missing from iris balance, the P&L, or the balance sheet, its status is almost certainly still draft. Promote it:

iris post journals/2026/05/2026-05-04-example-com-01.md

…or edit the status: field to posted and re-validate.

”iris: command not found”

The iris binary isn’t on this machine’s PATH yet. Install it (curl -fsSL https://irisbooks.jp/install.sh | sh on macOS/Linux, irm https://irisbooks.jp/install.ps1 | iex on Windows PowerShell), then check with iris version. If you’re working in a sandboxed AI environment, there is no copy bundled inside the book — the host runs iris mcp serve and your assistant calls the verbs over MCP instead.

Sync rejections (needs-attention)

iris validate checks file state, but the server runs additional rules when you push (chart-projection orphans, a journal referencing a raw/ file that isn’t uploaded, schema/immutability violations). When the server rejects a push, iris validate may end with a note like “N file(s) blocked in the sync queue” — the files are fine, the push was rejected.

To clear it:

iris attention list      # read the field-level reason

Then fix the cause — usually:

  • add the missing account to config/chart-of-accounts.yaml, or
  • make sure the referenced raw/... document is actually present and synced.

Then re-save the rejected journal. Its content hash changes, the engine drops the per-file suppression, and the push goes out automatically on the next sync.

If your fix was in a different file (e.g. you fixed the chart days ago and won’t touch the journal again), nudge the engine instead:

iris attention retry            # re-push everything in the queue
iris attention retry --path <relpath>   # just one file

Sync conflicts

If you and someone else (or you on another device) changed the same file, a push can conflict. The server version takes the canonical path, and your version is saved beside it as a <file>.conflicted sidecar. iris sync refuses to proceed while any sidecar exists, so nothing is lost.

iris conflicts list

Resolve each one. The usual way is to merge by hand: open the canonical file, fold in whatever you need from the .conflicted sidecar, delete the sidecar, and run iris sync again. To take one side wholesale instead:

iris conflicts resolve <path> --keep mine     # replace canonical with your version
iris conflicts resolve <path> --keep cloud    # discard your version

iris sync exits with code 3

Exit code 3 means a terminal disconnect. The summary (and the disconnectReason field of iris sync --json) says which kind:

  • deleted — the owner deleted the book on the server (web app → the book’s Settings → Danger zone). Your local files are intact — nothing was removed from your folder, and iris status shows Remote: deleted on the server. To keep working locally, edit config/book.yaml and set book_id back to your local id (iris status prints it). To reconnect to the cloud, create a new book (iris api books new) and link it (iris api books link <id> --force).
  • forbidden — your access was revoked (your credential is valid but you no longer hold a grant). Ask the book’s owner to re-invite you. If access was intentionally revoked, that’s expected.
  • auth_expired — your session is gone. Re-authenticate (iris api login) and run iris sync again.

”I need to change a sealed year”

A sealed fiscal year is locked: iris post refuses journals dated in it (“FY <n> is sealed (closed period) — run iris reopen <n> to amend it, then re-seal”), sync pushes into it are rejected by the server, and the web app and remote connector refuse edits too. The year’s files stay in your working tree — they just refuse writes. To amend the year, reopen it first:

iris reopen 2025      # unlocks the seal; the files are already in the working tree
# …make the correction…
iris sync
iris api seal --period 2025 <book-id>   # close the year again

The server records the corrections as post-seal edits — visible in the Activity log and badged in the web app. That’s by design: the correction is allowed and auditable, not hidden. Re-sealing supersedes the old seal in the audit chain.

”The web app shows different numbers than my CLI”

Almost always a sync gap or a status difference:

  • Run iris diff to see local changes you haven’t pushed, then iris sync.
  • Remember the web app, like the CLI, reports only posted entries — a draft you see locally won’t appear until it’s posted and synced.
  • Reports in the web app show a “freshness” note for when the server last recomputed; give a recent push a moment to project.

Still stuck?

  • Re-read Core concepts — most confusion is about status (drafts vs posted) or what sync does.
  • Check the in-book notes/open-questions.md — your AI files ambiguous items there.
  • For Japan tax specifics, see Japan tax & compliance; your AI verifies volatile values (rates, tables, form layouts) against the NTA’s current pages.