amark/gun · error · TypeError

First argument must be a string, Buffer, ArrayBuffer, Array,

Error message

First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.

What it means

This sea/buffer.js SafeBuffer.from polyfill mimics Node's Buffer.from. It throws a TypeError when called with no arguments or with a null/undefined first argument, because there is no data to construct a buffer-like SeaArray from.

Source

Thrown at sea/buffer.js:19

;(function(){

    require('./base64');
    // This is Buffer implementation used in SEA. Functionality is mostly
    // compatible with NodeJS 'safe-buffer' and is used for encoding conversions
    // between binary and 'hex' | 'utf8' | 'base64'
    // See documentation and validation for safe implementation in:
    // https://github.com/feross/safe-buffer#update
    var SeaArray = require('./array');
    function SafeBuffer(...props) {
      console.warn('new SafeBuffer() is depreciated, please use SafeBuffer.from()')
      return SafeBuffer.from(...props)
    }
    SafeBuffer.prototype = Object.create(Array.prototype)
    Object.assign(SafeBuffer, {
      // (data, enc) where typeof data === 'string' then enc === 'utf8'|'hex'|'base64'
      from() {
        if (!Object.keys(arguments).length || arguments[0]==null) {
          throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
        }
        const input = arguments[0]
        let buf
        if (typeof input === 'string') {
          const enc = arguments[1] || 'utf8'
          if (enc === 'hex') {
            const bytes = input.match(/([\da-fA-F]{2})/g)
            .map((byte) => parseInt(byte, 16))
            if (!bytes || !bytes.length) {
              throw new TypeError('Invalid first argument for type \'hex\'.')
            }
            buf = SeaArray.from(bytes)
          } else if (enc === 'utf8' || 'binary' === enc) { // EDIT BY MARK: I think this is safe, tested it against a couple "binary" strings. This lets SafeBuffer match NodeJS Buffer behavior more where it safely btoas regular strings.
            const length = input.length
            const words = new Uint16Array(length)
            Array.from({ length: length }, (_, i) => words[i] = input.charCodeAt(i))
            buf = SeaArray.from(words)
          } else if (enc === 'base64') {

View on GitHub (pinned to 552227599d)

Solutions

  1. Check the value is a non-null string/ArrayBuffer/array before calling from()
  2. Guard optional data sources (localStorage, config, JWT fields) before conversion
  3. If you need an empty buffer, pass an empty string or array instead of null
  4. Verify which Buffer implementation is loaded (sea/buffer.js polyfill vs Node Buffer) to know which validations apply

Example fix

// before
const key = SafeBuffer.from(localStorage.getItem('key'), 'utf8');
// after
const stored = localStorage.getItem('key');
if (typeof stored !== 'string') throw new Error('key not configured');
const key = SafeBuffer.from(stored, 'utf8');
Defensive patterns

Strategy: validation

Validate before calling

function isBufFromInput(v) {
  return v != null && (typeof v === 'string' || ArrayBuffer.isView(v) || v instanceof ArrayBuffer || Array.isArray(v));
}
if (!isBufFromInput(input)) throw new TypeError('from() needs non-null string/ArrayBuffer/array');

Type guard

const isNonNullData = (v) => v !== null && v !== undefined;

Try / catch

try {
  const buf = SafeBuffer.from(input, enc);
} catch (e) {
  if (e instanceof TypeError) {
    console.error('no data to buffer:', input);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling SafeBuffer.from() with zero arguments; calling SafeBuffer.from(null) or SafeBuffer.from(undefined); passing a variable that is null/undefined, e.g. from a failed lookup or empty JSON.parse result — note objects like {} or numbers do NOT throw here, only missing/nullish input does.

Common situations: Decoding a SEA token/proof where the field is absent; passing the result of sessionStorage/localStorage.getItem (null when missing) directly to Buffer.from; integration code assuming Node's Buffer exists when the code actually runs Gun's SafeBuffer polyfill (e.g. in browsers or sea builds).

Related errors


AI-assisted analysis of amark/gun@552227599d (2026-09-02). Data as JSON: /api/errors/a87ea721284b90c7. Report an issue: GitHub.