Xero Sync Works — Every Direction
Last week's release said Xero sync was restored. It wasn't, and we're sorry. There were two separate faults stacked on top of each other; fixing the first one simply revealed the second, which is what you would have seen as the invoiceBaseRows.map is not a function error on your Integrations page.
That second fault is now fixed, and this time we checked all four directions rather than just the one that was reported:
- Sending invoices to Xero — the reported failure.
- Sending clients to Xero as contacts.
- Bringing contacts in from Xero.
- Bringing your chart of accounts in from Xero.
All four were failing, and all four now work. Nothing was ever sent to Xero incorrectly — the sync stopped before it wrote anything, so your Xero data has not been altered or duplicated by this. It simply never arrived.
What To Expect On Your Next Sync
Everything that queued up goes across at once. If you have been invoicing as normal since 21 July, that backlog is larger than you might assume — none of it has reached Xero. Review the run before you send, especially the invoice list.
Your Integrations page will still show the old error message until the next sync starts, at which point it clears on its own. Your "Last synced" date will finally move forward again.
Two related fixes you may notice:
- The sync now reports the correct number of records still waiting to be sent. It previously always said zero, which made a partial sync look finished.
- Importing contacts from Xero was fetching your entire contact list every time instead of only what had changed since the last run. It is now properly incremental, so imports are faster and far less likely to hit Xero's rate limits.
Why This Took A Second Attempt
The honest answer is that our tests were checking the wrong thing. They simulated our database in a way that didn't match how it actually behaves, so they passed while the real code failed — which is why a completely broken integration looked healthy to us and got reported by a customer instead of caught by us.
We have fixed the tests themselves, not just the code, and added checks that fail loudly if anyone recreates that same mismatch. We have also started work on alerting so that an integration failing this completely raises a flag on our side immediately, rather than waiting for someone to notice a message on a page.
Behind The Scenes
Reliability improvements to our database result handling, with new automated checks to prevent this class of fault recurring.