usebruno/bruno · error · Error

Invalid URL format: ${url}

Error message

Invalid URL format: ${url}

What it means

Thrown by splitUrl inside transformUrl when splitting the URL on the /:\/\// regex produces more than two segments — i.e. the URL contains multiple '://' occurrences. A well-formed URL splits into at most two parts (protocol + rest), so reaching the else branch means the input URL is structurally malformed for the purpose of Postman export.

Source

Thrown at packages/bruno-converters/src/postman/bruno-to-postman.js:88

  };

  const postmanUrl = { raw: url };

  /**
   * Splits a URL into its protocol, host and path.
   *
   * @param {string} url - The URL to be split.
   * @returns {Object} An object containing the protocol and the raw host/path string.
   */
  const splitUrl = (url) => {
    const urlParts = url.split(urlRegexPatterns.protocolAndRestSeparator);
    if (urlParts.length === 1) {
      return { protocol: '', rawHostAndPath: urlParts[0] };
    } else if (urlParts.length === 2) {
      const [hostAndPath, _] = urlParts[1].split(urlRegexPatterns.queryStringSeparator);
      return { protocol: urlParts[0], rawHostAndPath: hostAndPath };
    } else {
      throw new Error(`Invalid URL format: ${url}`);
    }
  };

  /**
   * Splits the host and path from a raw host/path string.
   *
   * @param {string} rawHostAndPath - The raw host and path string to be split.
   * @returns {Object} An object containing the host and path.
   */
  const splitHostAndPath = (rawHostAndPath) => {
    const [host, path = ''] = rawHostAndPath.split(urlRegexPatterns.hostAndPathSeparator);
    return { host, path };
  };

  try {
    const { protocol, rawHostAndPath } = splitUrl(url);
    postmanUrl.protocol = protocol;

View on GitHub (pinned to 9bdd81c7bd)

Solutions

  1. Sanitize the request URL before export: strip duplicate protocol prefixes (`url.replace(/^(\w+):\/\/.*/, ...)`).
  2. Move the literal '://' out of the path/query (URL-encode it as %3A%2F%2F).
  3. If the URL legitimately needs multiple schemes, pre-process it into protocol/host/path manually before passing to the exporter.

Example fix

// before
const url = 'http://https://api.example.com/users';
transformUrl(url, params); // throws Invalid URL format

// after — normalize to single scheme
const safeUrl = url.replace(/^(\w+):\/\//, '').replace(/^(https?:)?\/\//, '$1//');
transformUrl(safeUrl || 'http://' + url, params);
Defensive patterns

Strategy: validation

Validate before calling

const hasSingleScheme = (u) => (typeof u === 'string' ? (u.match(/:\/\//g) || []).length <= 1 : false);
// before export:
if (!hasSingleScheme(req.url)) req.url = req.url.replace(/^(\w+):\/\/.*/, '$1://').replace(/:\/\/+/g, '://');

Type guard

const isValidSingleSchemeUrl = (u) => typeof u === 'string' && (u.match(/:\/\//g) || []).length <= 1;

Try / catch

try {
  return transformUrl(url, params);
} catch (e) {
  if (e.message.startsWith('Invalid URL format')) {
    return transformUrl('', params); // fall back to empty URL
  }
  throw e;
}

Prevention

When it happens

Trigger: Exporting a Bruno request to Postman where the request URL contains multiple '://' sequences. Examples: 'http://https://api.example.com', 'ws://wss://host', or a URL with a '://' literal inside a path/query that the simple regex cannot disambiguate.

Common situations: A request URL copy-pasted with a duplicated scheme; WebSocket URLs that were concatenated; templated URLs where a {{protocol}} variable resolved to include '://'; URLs containing '://' inside a query parameter.

Related errors


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