book.replayJournal
Replay a GnuCash .log journal onto the open book: create, update or delete transactions by GUID.
Replays a GnuCash .log journal onto the open book: each record creates, updates or deletes a transaction by GUID.
Use it to recover work from a journal after a crash, by replaying the journal of the book you lost onto the last
saved file. created, updated and deleted list the GUIDs touched; notFound lists records whose transaction was
not there to update or delete.
Replaying is journaled like any other change, and it changes transactions only, not accounts: records that need an
account the book lacks are refused unless skipInvalid is true, which skips them and lists them in
skippedRecords. The file is read on the server, so path is relative to where it runs.
Examples
The journal of an open book is the journal field of book.info. A path that does not exist
fails with io-error, and nothing is changed:
Example: with a copy of the reports/test-data example book open as book.gnucash.
JSON-RPC
Request:
{"jsonrpc":"2.0","id":1,"method":"book.replayJournal","params":{"path":"missing.log"}}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": 1008,
"message": "…",
"data": {
"path": "…",
"help": "error/io-error"
}
}
}
Command line
red-ale exec --book book.gnucash book.replayJournal '{"path":"missing.log"}'
It fails with exit status 2, printing on standard error:
{
"error": {
"code": 1008,
"message": "…",
"data": {
"path": "…",
"help": "error/io-error"
}
}
}
MCP tool call
Tool call:
{"name":"book.replayJournal","arguments":{"path":"missing.log"}}
Result:
{
"isError": true,
"structuredContent": {
"error": {
"code": 1008,
"name": "io-error",
"message": "…",
"data": {
"path": "…",
"help": "error/io-error"
}
}
}
}
A transaction posted and then lost, because the book was closed without saving, comes back from the journal. The
journal is named by the local time it was opened at, here book.gnucash.20240701120000.log:
Example: with a new, empty book open as book.gnucash, at 2024-07-01T12:00:00Z.
JSON-RPC
Request:
{"jsonrpc":"2.0","id":1,"method":"account.create","params":{"name":"Checking","type":"BANK","commodity":"USD"}}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": "…"
}
Request:
{"jsonrpc":"2.0","id":2,"method":"account.create","params":{"name":"Rent","type":"EXPENSE","commodity":"USD"}}
Response:
{
"jsonrpc": "2.0",
"id": 2,
"result": "…"
}
Request:
{"jsonrpc":"2.0","id":3,"method":"book.save","params":{}}
Response:
{
"jsonrpc": "2.0",
"id": 3,
"result": "…"
}
Request:
{"jsonrpc":"2.0","id":4,"method":"transaction.post","params":{"datePosted":"2024-07-01","description":"Rent","splits":[{"account":"Checking","value":"-750.00"},{"account":"Rent","value":"750.00"}]}}
Response:
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"guid": "…",
"…": "…"
}
}
Request:
{"jsonrpc":"2.0","id":5,"method":"book.close","params":{"discard":true}}
Response:
{
"jsonrpc": "2.0",
"id": 5,
"result": "…"
}
Request:
{"jsonrpc":"2.0","id":6,"method":"book.open","params":{"path":"book.gnucash"}}
Response:
{
"jsonrpc": "2.0",
"id": 6,
"result": {
"counts": {
"transactions": 0,
"…": "…"
},
"…": "…"
}
}
Request:
{"jsonrpc":"2.0","id":7,"method":"book.replayJournal","params":{"path":"book.gnucash.20240701120000.log"}}
Response:
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"created": [
"…"
],
"updated": [],
"deleted": [],
"notFound": [],
"…": "…"
}
}
Command line
red-ale exec --book book.gnucash --script - <<'EOF'
account.create {"name":"Checking","type":"BANK","commodity":"USD"}
account.create {"name":"Rent","type":"EXPENSE","commodity":"USD"}
book.save {}
transaction.post {"datePosted":"2024-07-01","description":"Rent","splits":[{"account":"Checking","value":"-750.00"},{"account":"Rent","value":"750.00"}]}
book.close {"discard":true}
book.open {"path":"book.gnucash"}
book.replayJournal {"path":"book.gnucash.20240701120000.log"}
EOF
It prints:
[
"…",
"…",
"…",
{
"guid": "…",
"…": "…"
},
"…",
{
"counts": {
"transactions": 0,
"…": "…"
},
"…": "…"
},
{
"created": [
"…"
],
"updated": [],
"deleted": [],
"notFound": [],
"…": "…"
}
]
MCP tool call
Tool call:
{"name":"account.create","arguments":{"name":"Checking","type":"BANK","commodity":"USD"}}
Result:
{
"content": [
{
"type": "text",
"text": "\"…\""
}
]
}
Tool call:
{"name":"account.create","arguments":{"name":"Rent","type":"EXPENSE","commodity":"USD"}}
Result:
{
"content": [
{
"type": "text",
"text": "\"…\""
}
]
}
Tool call:
{"name":"book.save","arguments":{}}
Result:
{
"content": [
{
"type": "text",
"text": "\"…\""
}
]
}
Tool call:
{"name":"transaction.post","arguments":{"datePosted":"2024-07-01","description":"Rent","splits":[{"account":"Checking","value":"-750.00"},{"account":"Rent","value":"750.00"}]}}
Result:
{
"structuredContent": {
"guid": "…",
"…": "…"
}
}
Tool call:
{"name":"book.close","arguments":{"discard":true}}
Result:
{
"content": [
{
"type": "text",
"text": "\"…\""
}
]
}
Tool call:
{"name":"book.open","arguments":{"path":"book.gnucash"}}
Result:
{
"structuredContent": {
"counts": {
"transactions": 0,
"…": "…"
},
"…": "…"
}
}
Tool call:
{"name":"book.replayJournal","arguments":{"path":"book.gnucash.20240701120000.log"}}
Result:
{
"structuredContent": {
"created": [
"…"
],
"updated": [],
"deleted": [],
"notFound": [],
"…": "…"
}
}
Effect: write, on the Book.
Params
Params of book.replayJournal.
path(string, required): The journal: a<book>.<timestamp>.logfile.skipInvalid(boolean): Skip records that cannot be applied (for example an unbalanced transaction) instead of refusing the replay.
Result
What book.replayJournal did.
records(integer (uint), required): Records read.created(array of Guid, required): Transactions created.updated(array of Guid, required): Transactions updated.deleted(array of Guid, required): Transactions deleted.notFound(array of Guid, required): Deletions of transactions the book does not have.skippedRecords(array of string, required): Records skipped, with why.skippedLines(array of string, required): Lines that could not be read, asline N: reason.