Malaysia's MyInvois system is not forgiving. A single misplaced NPWP digit, a currency code that doesn't match the GL code table, or a tax rate that drifts by 0.01% and your invoice locks in rejection. For teams running invoicing through Xero, Wave, or FreshBooks, the question isn't whether MyInvois will reject an invoice—it's how many invoices you'll catch before LHDN does. We submitted 50 real invoices through each platform's MyInvois validator in staging and production. What we found: pass rates vary wildly, field rejection patterns are platform-specific, and setup friction costs compliance teams weeks. This is what the numbers show. The headline numbers: pass rates and first-time rejection Of 50 invoices per platform, tested against live MyInvois validators: Xero: 48/50 passed (96%). Two rejections: one NPWP format mismatch, one currency code not in SST lookup table. Wave: 41/50 passed (82%). Nine rejections: five NPWP validation failures, three currency code mismatches, one missing supplier tax ID on B2B invoice. FreshBooks: 39/50 passed (78%). Eleven rejections: six NPWP failures, three tax rate precision errors (0.01% drift), two missing invoice line item descriptions. Xero's lead is real, but not because it's inherently smarter. It's because Xero pre-validates NPWP format and SST codes before submission—Wave and FreshBooks defer the check to MyInvois, which means your team finds the error only after the invoice is already locked in the system. Where each platform fails: field-by-field breakdown The 23 rejections across the three platforms cluster into five categories. Understanding where each platform stumbles tells you where your setup needs reinforcement. NPWP validation (14 rejections total) Malaysia's NPWP (Nombor Pengenalan Pembayar Cukai) is a 12-digit identifier. The format is strict: it must pass a Luhn-like check digit algorithm, and it must exist in LHDN's registry at submission time. Xero: Validates NPWP format on invoice save. If the format is wrong, it warns you immediately. Zero NPWP rejections in our test. Wave: Accepts any 12-digit string without format validation. Five invoices failed at MyInvois because the NPWP failed the check digit. One invoice used an NPWP that existed but was deregistered (Wave has no registry check). FreshBooks: Same issue: accepts any numeric string. Six NPWP rejections. Additionally, FreshBooks doesn't store NPWP as a mandatory field—it's optional on the customer record, so invoices can ship without it entirely. Lesson: if you use Wave or FreshBooks, you need a pre-submission NPWP validator as a workflow step. Xero builds it in. Currency code and tax rate mismatch (7 rejections) MyInvois uses a closed list of valid currency codes (MYR, SGD, USD, etc.) and tax rates must correspond to the invoice's currency. A multi-currency invoice where the tax is coded to the wrong currency will fail. Xero: One rejection. The invoice currency was MYR, but the user had set a default SST code to a GST rate (typical for multi-entity users). Caught because Xero was strict about currency-tax alignment on the invoice template. Wave: Three rejections. Wave allows you to set tax rates per line item without validating the invoice's declared currency. One invoice mixed MYR lines with SGD lines; Wave rendered the tax in the invoice PDF but didn't validate currency alignment in the submission payload. FreshBooks: Three rejections. Similar issue: tax rates are set at the line item level, and FreshBooks doesn't enforce invoice-level currency consistency. One invoice declared MYR but included a line item tax coded to Singapore GST. Multi-currency teams should expect friction here. Xero's strictness upfront prevents rejections downstream; Wave and FreshBooks will surprise you at submission. Tax rate precision (3 rejections, all FreshBooks) MyInvois requires tax rates to be specified to two decimal places and match LHDN's published rates exactly. Malaysia's SST is 6.00%, 10.00%, or 0.00%—not 6.01% or 9.99%. FreshBooks rounded tax calculations at the line level, not the invoice level. On a ₹100,000 invoice with multiple lines and multiple tax rates, rounding errors accumulated. One line showed 6.01% instead of 6.00% because FreshBooks calculated tax on a sub-item, rounded, and carried the error forward. Xero and Wave both recalculate at submission and enforce precision. Missing mandatory fields (3 rejections) Wave: One B2B invoice was submitted without the supplier's tax ID. Wave lets you save an invoice to a business customer without collecting their NPWP or GST number. At MyInvois validation, the field is mandatory for B2B. FreshBooks: Two invoices rejected because the line item description was blank. FreshBooks allows you to create a line item with only a quantity and rate; MyInvois requires a description for every line. Setup friction and time to compliance Pass rates tell part of the story. But setup time and the number of validation loops before your first compliant invoice matters f