danny-avila/LibreChat · error · Error

Failed to convert base64 to buffer: ${error.message}

Error message

Failed to convert base64 to buffer: ${error.message}

What it means

Outer wrapper thrown by base64ToBuffer's catch when any error inside the try escapes — including the explicit 'Invalid base64 string' throw (error 137) or an unexpected exception during regex match or Buffer.from. The wrapper prefixes the message so callers always see a consistent 'Failed to convert base64 to buffer:' shape. The underlying cause is in the interpolated `error.message`.

Source

Thrown at api/server/services/Files/process.js:1251

 * @returns {Buffer<ArrayBufferLike>}
 */
function base64ToBuffer(base64String) {
  try {
    const typeMatch = base64String.match(/^data:([A-Za-z-+/]+);base64,/);
    const type = typeMatch ? typeMatch[1] : '';

    const base64Data = base64String.replace(/^data:([A-Za-z-+/]+);base64,/, '');

    if (!base64Data) {
      throw new Error('Invalid base64 string');
    }

    return {
      buffer: Buffer.from(base64Data, 'base64'),
      type,
    };
  } catch (error) {
    throw new Error(`Failed to convert base64 to buffer: ${error.message}`);
  }
}

async function saveBase64Image(
  url,
  { req, file_id: _file_id, filename: _filename, endpoint, context, resolution },
) {
  const appConfig = req.config;
  const effectiveResolution = resolution ?? appConfig.fileConfig?.imageGeneration ?? 'high';
  const file_id = _file_id ?? v4();
  let filename = `${file_id}-${_filename}`;
  const { buffer: inputBuffer, type } = base64ToBuffer(url);
  if (!path.extname(_filename)) {
    const extension = mime.getExtension(type);
    if (extension) {
      filename += `.${extension}`;
    } else {
      throw new Error(`Could not determine file extension from MIME type: ${type}`);

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Inspect the trailing `: <reason>` — 'Invalid base64 string' means empty after prefix (see error 137); other text indicates a Buffer.from failure.
  2. Sanitize the input: strip whitespace/newlines and confirm the body matches `^[A-Za-z0-9+/]+=*$`.
  3. Re-encode the source via `Buffer.from(buf).toString('base64')` to guarantee a clean alphabet.
  4. Avoid passing URL-decoded payloads — preserve `+` and `/` and the trailing `=` padding.

Example fix

// before
const clean = raw.replace(/\s/g, ''); // partial fix, still allows bad chars

// after
const body = raw.replace(/^data:[^;]+;base64,/, '').replace(/\s/g, '');
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(body)) throw new Error('Not valid base64');
const { buffer } = base64ToBuffer(`data:${mime};base64,${body}`);
Defensive patterns

Strategy: validation

Validate before calling

function sanitizeBase64(raw) {
  const body = raw.replace(/^data:[^;]+;base64,/, '').replace(/\s/g, '');
  if (!/^[A-Za-z0-9+/]*={0,2}$/.test(body)) {
    throw new Error('Invalid base64 characters');
  }
  return body;
}

Try / catch

try { base64ToBuffer(s); }
catch (e) {
  if (/Failed to convert base64 to buffer/.test(e.message)) {
    return res.status(400).json({ error: 'Malformed image data; please re-upload.' });
  }
  throw e;
}

Prevention

When it happens

Trigger: Any exception inside base64ToBuffer: the inner 'Invalid base64 string' throw, a malformed input causing `Buffer.from` to throw on invalid base64 characters, or an unlikely regex engine error. In practice most cases are the empty-payload case (which surfaces as '...Invalid base64 string') or non-base64 characters in the body.

Common situations: Caller passes a string with characters outside the base64 alphabet (whitespace, unicode, control chars); URL-encoded data URL whose `+`/`/` were mangled; truncated payload; the empty-payload case from error 137 bubbled through this wrapper.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/0bfb0826db1e2739. Report an issue: GitHub.