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
- Sanitize the request URL before export: strip duplicate protocol prefixes (`url.replace(/^(\w+):\/\/.*/, ...)`).
- Move the literal '://' out of the path/query (URL-encode it as %3A%2F%2F).
- 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
- Normalize request URLs at collection load time to a single scheme.
- URL-encode any literal '://' that legitimately appears in path or query.
- Add a pre-export lint pass over item.request.url.
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
- Invalid Git URL
- No definitions found in WSDL
- Workspace path not found
- Invalid environment: expected an object
- Invalid environment: missing or invalid variables array
AI-assisted analysis of usebruno/bruno@9bdd81c7bd (2026-08-13).
Data as JSON: /api/errors/3d9ee67edf717505.
Report an issue: GitHub.