Troubleshooting
This page covers common integration failures.
Browser says SharedArrayBuffer is unavailable
The default @libraz/formulon entry is single-threaded and does not need SharedArrayBuffer. This error applies when the application explicitly loads @libraz/formulon/threads or another pthread-backed integration. Serve that page with cross-origin isolation headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corpVite preview is not your production host
Check the headers in the actual deployed environment. A local dev server passing does not prove the CDN or app server is configured correctly.
Vite warns about node: imports
The WASM package contains a Node branch for Node runtime support, and the threads entry also contains a node:worker_threads branch. Browser bundlers may warn about node:module or node:worker_threads. In Vite, exclude the package from optimizeDeps and mark node: imports external.
import { defineConfig } from 'vite'
export default defineConfig({
optimizeDeps: { exclude: ['@libraz/formulon'] },
build: {
target: 'es2022',
rollupOptions: { external: [/^node:/] }
}
})Workbook load returns an invalid handle
In WASM, loadBytes(bytes) does not throw on bad input. Check wb.isValid() immediately and read Module.lastErrorMessage(); for a file that is not a ZIP archive, the message comes from the ZIP reader.
const wb = Module.Workbook.loadBytes(bytes)
try {
if (!wb.isValid()) {
throw new Error(Module.lastErrorMessage())
}
} finally {
wb.delete()
}Python's Workbook.load(data) raises FormulonError instead of returning an invalid handle.
Formula returns an Excel error
Excel errors are values. #DIV/0!, #VALUE!, and #NAME? do not mean the host API failed. Check value.kind for ValueKind.Error and read value.errorCode (error_code in Python); Module.errorDisplayName(code) turns the code into text such as #DIV/0!.
The CLI follows the same rule for malformed eval syntax: formulon eval '=SUM(' prints #NAME? to stdout and exits 0. Check stdout when a script must reject malformed formula text; a non-zero exit is reserved for usage, IO, or engine failures.
Workbook mutation has a separate parse boundary. setFormula() rejects malformed text with the kParserUnexpectedToken status and leaves the existing formula and cached value unchanged. A malformed formula already stored in an XLSX or XLSB file can still be loaded; after recalc() its cell value is #NAME?. This lets a file round-trip while exposing the bad formula to a compatibility check.
A validation unexpectedly rejects blank cells
allowBlank defaults to false when omitted on WASM and Native Node, matching Python. Set allowBlank: true (or Python's allow_blank=True) when the validation should accept an empty cell.
Python cannot load the WASM runtime
Install the published wheel so pip can resolve a compatible wasmtime wheel, or run the staging command from the repository root:
make python-packageThe source-tree import expects the staged C-ABI WASM module at packages/python/formulon/_wasm/formulon_capi.wasm. To use a module built elsewhere, set FORMULON_WASM_PATH to its path; the bundled location is checked first.
CLI result differs from Excel
Check these first:
- whether the function is an unavailable service stub — registered, but intentionally returning an Excel error, such as
PYor CUBE connection functions, - whether the workbook depends on locale behavior outside the selected profile (the default is
win-365-en_US), - whether the CLI or host applied the intended full profile id (locale translation uses the profile id, not a numeric locale code),
- whether volatile functions are involved,
- whether the workbook structure is preserved but not evaluated.
Create a minimal formula case and compare it with Formula coverage and Oracle testing.