---
sidebar_position: 2
title: Troubleshooting
hide_table_of_contents: true
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
Here are some common errors and their resolutions.  This is not comprehensive.
The [issue tracker](https://git.sheetjs.com/SheetJS/sheetjs/issues) has a
wealth of information and user-contributed examples.
**Many of these errors have been fixed in newer releases!**  Ensure that the
latest version of the library is being used. Some legacy endpoints are out of
date.  [Review the Installation instructions.](/docs/getting-started/installation)
If issues are not covered in the docs or the issue tracker, or if a solution is
not discussed in the documentation, we would appreciate a bug report.
:::info Special Thanks
Special thanks to the early adopters and users for discovering and sharing many
workarounds and solutions!
:::
## Errors
#### Uncaught TypeError: Cannot read property of undefined
Errors include
```
Uncaught TypeError: Cannot read property 'read' of undefined
Uncaught TypeError: Cannot read property 'writeFile' of undefined
Uncaught TypeError: Cannot read property 'utils' of undefined
```
The root cause is an undefined `XLSX` variable.  This usually means the library
was not properly loaded.
[Review the Installation instructions.](/docs/getting-started/installation)
If the error shows up while using the latest version, projects may require
other configuration or loading strategies.
Upgrade Note (click to show)
Older versions of the library only shipped with CommonJS and standalone script.
Webpack and other bundlers supported CommonJS dependencies with default import:
```js
// old way
import XLSX from "xlsx";
```
Newer versions of the library ship with an ESM build.  When upgrading, imports
should be updated:
```js
// new way
import * as XLSX from "xlsx";
import * as cptable from "xlsx/dist/cpexcel.full.mjs";
XLSX.set_cptable(cptable);
```
Newer releases support tree shaking, and special methods like `writeFileXLSX`
help reduce bundle size.
[The bundler note](/docs/getting-started/installation/frameworks) explains in
further detail.
Technical Limitations (click to show)
V8 (Node/Chrome) have a maximum string length that has changed over the years.
Node 16 and Chrome 106 enforce a limit of 536870888 characters. This issue will
manifest with error messages such as `Invalid string length`.
There are memory bottlenecks associated with string addresses. A number of bugs
have been reported to the V8 and Chromium projects on this subject. While those
bugs are being resolved, for sheets containing hundreds of thousands of rows,
dense mode worksheets should be used.
Workaround (click to show)
:::warning Legacy workaround
This solution is not recommended for production deployments.  Native support
for `ArrayBuffer` was added in library version `0.9.9`.
:::
After reading data with `FileReader#readAsArrayBuffer`, manually translate to
binary string and call `XLSX.read` with type `"binary"`
```js
document.getElementById('file-object').addEventListener("change", function(e) {
  var files = e.target.files,file;
  if (!files || files.length == 0) return;
  file = files[0];
  var fileReader = new FileReader();
  fileReader.onload = function (e) {
    var filename = file.name;
    // pre-process data
    var binary = "";
    var bytes = new Uint8Array(e.target.result);
    var length = bytes.byteLength;
    for (var i = 0; i < length; i++) {
      binary += String.fromCharCode(bytes[i]);
    }
    // call 'xlsx' to read the file
    var oFile = XLSX.read(binary, {type: 'binary', cellDates:true, cellStyles:true});
  };
  fileReader.readAsArrayBuffer(file);
});
```
FileSaver.js integration (click to show)
_Standalone Build_
{`\
`}
_Frameworks and Bundlers_
At the time of writing, `file-saver@2.0.5` leaks `saveAs` to the global scope,
so merely importing the module works:
```js
import FileSaver from 'file-saver'; // as a side effect, `saveAs` is visible
import { writeFile } from 'xlsx'; // writeFile will use the global `saveAs`
```
More Code Snippets (click to show) 
`set_sheet_range` changes a sheet's range given a general target spec that can include only the start or end cell:
```js
/* given the old range and a new range spec, produce the new range */
function change_range(old, range) {
  var oldrng = XLSX.utils.decode_range(old), newrng;
  if(typeof range == "string") {
    if(range.charAt(0) == ":") newrng = {e:XLSX.utils.decode_cell(range.substr(1))};
    else if(range.charAt(range.length - 1) == ":") newrng = {s:XLSX.utils.decode_cell(range.substr(0, range.length - 1))};
    else newrng = XLSX.utils.decode_range(range);
  } else newrng = range;
  if(newrng.s) {
    if(newrng.s.c != null) oldrng.s.c = newrng.s.c;
    if(newrng.s.r != null) oldrng.s.r = newrng.s.r;
  }
  if(newrng.e) {
    if(newrng.e.c != null) oldrng.e.c = newrng.e.c;
    if(newrng.e.r != null) oldrng.e.r = newrng.e.r;
  }
  return XLSX.utils.encode_range(oldrng);
}
/* call change_sheet and modify worksheet */
function set_sheet_range(sheet, range) {
  sheet['!ref'] = change_range(sheet['!ref'], range);
}
```
_Adding a cell to a range_
```js
function range_add_cell(range, cell) {
  var rng = XLSX.utils.decode_range(range);
  var c = typeof cell == 'string' ? XLSX.utils.decode_cell(cell) : cell;
  if(rng.s.r > c.r) rng.s.r = c.r;
  if(rng.s.c > c.c) rng.s.c = c.c;
  if(rng.e.r < c.r) rng.e.r = c.r;
  if(rng.e.c < c.c) rng.e.c = c.c;
  return XLSX.utils.encode_range(rng);
}
range_add_cell("A1:C3","B2")
function add_to_sheet(sheet, cell) {
  sheet['!ref'] = range_add_cell(sheet['!ref'], cell);
}
```