usebruno/bruno · error · Error

Failed to parse ${context}: ${error.message}

Error message

Failed to parse ${context}: ${error.message}

What it means

Thrown by safeParseJSON in the WebSocket client when JSON.parse fails on an inbound or user-supplied string. The wrapper prepends the calling context to the message and console.errors the original string plus the parse error before re-throwing, so debugging info is captured. Any caller that hands a non-JSON string to safeParseJSON triggers it.

Source

Thrown at packages/bruno-requests/src/ws/ws-client.js:21

import { getParsedWsUrlObject } from './ws-url';

/**
 * Safely parse JSON string with error handling
 * @param {string} jsonString - The JSON string to parse
 * @param {string} context - Context for error messages
 * @returns {Object} Parsed object or throws error with context
 * @throws {Error} If JSON parsing fails
 */
const safeParseJSON = (jsonString, context = 'JSON string') => {
  try {
    return JSON.parse(jsonString);
  } catch (error) {
    const errorMessage = `Failed to parse ${context}: ${error.message}`;
    console.error(errorMessage, {
      originalString: jsonString,
      parseError: error
    });
    throw new Error(errorMessage);
  }
};

const normalizeMessageByFormat = (message, format) => {
  if (!message) {
    return '';
  }
  switch (format) {
    case 'json':
      // If it was already stringified, do not double encode
      if (typeof message === 'string') {
        return message;
      }
      return JSON.stringify(message);
    case 'raw':
    case 'xml':
      return message;
    default: {

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Confirm the server actually emits JSON for the frame being parsed; if it can emit other formats, branch on message type before calling safeParseJSON.
  2. If the frame is text-not-JSON by design, treat it as raw (use the 'raw'/'xml' normalizeMessageByFormat branch) instead of forcing JSON.
  3. Strip a leading BOM or whitespace before parsing: jsonString.replace(/^\uFEFF\s*/, '').
  4. For partial frames, ensure the WS client is not splitting on a wrong delimiter; assemble complete messages first.

Example fix

// before
const parsed = safeParseJSON(event.data, 'server message');

// after
const raw = typeof event.data === 'string' ? event.data.replace(/^\uFEFF\s*/, '') : '';
if (!raw.startsWith('{') && !raw.startsWith('[')) {
  console.warn('non-JSON frame, treating as raw', raw);
} else {
  const parsed = safeParseJSON(raw, 'server message');
}
Defensive patterns

Strategy: try-catch

Validate before calling

function looksLikeJson(s) {
  if (typeof s !== 'string') return false;
  const t = s.replace(/^\uFEFF\s*/, '').trim();
  return t.startsWith('{') || t.startsWith('[');
}
// only invoke safeParseJSON when the frame is plausibly JSON
const data = looksLikeJson(frame) ? safeParseJSON(frame, 'server message') : frame;

Type guard

function isJsonParseError(e) {
  return e instanceof Error && /^Failed to parse .+:/.test(e.message);
}

Try / catch

try {
  return safeParseJSON(raw, 'ws.serverMessage');
} catch (e) {
  if (!isJsonParseError(e)) throw e;
  console.warn('dropping non-JSON frame', { len: raw?.length, head: raw?.slice?.(0, 64) });
  return null; // or route to a raw-text handler
}

Prevention

When it happens

Trigger: The server sends a plain-text, binary, XML, or HTML frame on a channel the client assumed was JSON; a partial/malformed frame is delivered; the user typed a non-JSON message into a 'json' format send box; BOM or control characters precede the JSON; the message is a valid JSON fragment that needs reassembly.

Common situations: WS endpoint that mixes text and JSON frames; reverse proxy returning an HTML error page over the WS upgrade; client/server version mismatch on the message schema; user pasting free text into a JSON-mode send field; locale-specific number formatting producing trailing commas.

Understand the failure class

Related errors


AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13). Data as JSON: /api/errors/c848c34fdc118500. Report an issue: GitHub.