POST /api/v1/assertions broken — submits Beancount source string to Fava JSON API #39
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
POST /libra/api/v1/assertionsalways returns 500 because the create handler hands a Beancount source-format string tofava.add_entry, which expects a dict and serialises it as JSON to Fava's/api/add_entries. Fava 500s on the malformed payload.End user impact: the entire balance-assertion / reconciliation feature is currently non-functional.
Repro
Returns:
Where
views_api.py:2993-3010:beancount_format.py:113-141:The fix has to land on whichever side owns the contract:
format_balancereturn a dict with{"t": "Balance", "date": ..., "account": ..., "amount": f"{n} {currency}", "tolerance": ...}so it composes withfava.add_entry. Fava'sadd_entriesdoes accept Balance directives this way (seefava/json_api.py—put_add_entriesdeserialises any directive type, not only Transactions).fava.add_entryentirely for balance assertions and use Fava's/api/sourceendpoint to append the source line directly. More fragile (file-write race, the libra-#36 sibling), but matchesformat_balance's current return type.Option 1 is the consistent thing to do — every other libra entry path goes through
fava.add_entrywith a dict.Caught by
The reconciliation test file
tests/test_reconciliation_api.py— 7 of 12 tests fail with this 500. The 5 that pass don't reach the broken Fava write (auth-gate, validation, listing, unknown-account, daily-task entry point all return before the bad path).Test file marks the affected tests as
xfailpointing at this issue until the fix lands.Surfaced alongside
This was found together with libra-#38 (validation.py exception-handling gap) and likely shares a single PR cycle — both are small, contained, in the assertion/validation surface.
Scope
beancount_format.format_balance— change return type fromstrtodict[str, Any]matching Fava's Balance directive shape.views_api.py: api_create_balance_assertion— no change if (1) is taken.format_balance(currently only the assertion endpoint).crud.check_balance_assertionre-check side and/reconciliation/check-alllikely already work since they read balances via the existing BQL path.Not blocking other libra work but blocks the reconciliation feature entirely.