{"record":{"id":"a1cd97f015000c28","repo":"NationalSecurityAgency/ghidra","slug":"unable-to-infer-bsim-url-from","errorCode":null,"errorMessage":"Unable to infer BSim URL from: {}","messagePattern":"Unable to infer BSim URL from: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java","lineNumber":89,"sourceCode":"\t * Alternately -url- can reference a ghidra server, as indicated by the \"ghidra\" protocol.\n\t *    In this case the true BSim URL is derived from ghidra URL in some way\n\t * @param urlString is the \"related\" URL\n\t * @return the root BSim URL\n\t * @throws MalformedURLException if the given URL string cannot be parsed\n\t * @throws URISyntaxException if the given URL string cannot be parsed\n\t * @throws IllegalArgumentException if local ghidra URL is specified\n\t */\n\tpublic static URL deriveBSimURL(String urlString)\n\t\t\tthrows IllegalArgumentException, MalformedURLException, URISyntaxException {\n\t\tURL url = new URI(urlString).toURL();\t// URL used only for parsing purposes\n\t\tString protocol = url.getProtocol();\n\t\tif (\"postgresql\".equals(protocol) || \"https\".equals(protocol) ||\n\t\t\t\"elastic\".equals(protocol) || \"file\".equals(protocol)) {\n\t\t\tcheckBSimServerURL(url);\n\t\t\treturn url; // URL already corresponds to BSim server protocol\n\t\t}\n\t\tif (!GhidraURL.isServerRepositoryURL(url)) {\n\t\t\tthrow new IllegalArgumentException(\"Unable to infer BSim URL from: \" + url);\n\t\t}\n\t\tString path = url.getPath();\t\t\t\t\t\t\t// Get the full path of the URL\n\t\tif (path == null || path.length() == 0 || path.equals(\"/\")) {\t\t// There must always be some kind of path, so we can derive the repository\n\t\t\tthrow new MalformedURLException(\"URL is missing a repository path\");\n\t\t}\n\t\tint endrepos = path.indexOf('/', 1);\t// Find the end of the first level of the path\n\t\tString repositoryURL;\n\t\tif (url.getProtocol().equals(GhidraURL.PROTOCOL)) {\t// Is this a ghidra URL\n\t\t\t// TODO: we could set things up so that a ghidra server could be queried for its associated BSim server\n\t\t\t// \"ghidra://host/repo?service=bsim\"\n\t\t\t// String repositoryURL = \"ghidra://\" + ghidraURL.getAuthority() + \"?service=bsim\";\n\n\t\t\t// Currently, all we do is assume that the BSim server is a PostgreSQL server\n\t\t\t// on the same host and with the same repo name as the ghidra server\n\t\t\trepositoryURL = \"postgresql://\" + url.getHost();\t\t// Just use the hostname\n\t\t}\n\t\telse {\n\t\t\t// For all other URL forms, we assume we are being handed the protocol and hostname (authority)","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java#L71-L107","documentation":"deriveBSimURL() first tries to parse the URL and check if its protocol is a native BSim protocol (postgresql/https/elastic/file). If not, it checks GhidraURL.isServerRepositoryURL(). If that also returns false, IllegalArgumentException is thrown — the URL is neither a direct BSim URL nor a Ghidra server repository URL from which a BSim URL can be derived.","triggerScenarios":"Calling deriveBSimURL(urlString) where the URL protocol is not a BSim protocol AND GhidraURL.isServerRepositoryURL(url) returns false. The string doesn't resolve to any known BSim or Ghidra server format.","commonSituations":"User provides a bare hostname without protocol; user provides a local filesystem path without 'file:' prefix; user provides an http URL (not in the BSim protocol set); malformed URL string; user provides a URL with an unrecognized scheme (e.g., ftp, ssh).","solutions":["Prefix the URL with a valid BSim protocol: postgresql://, https://, elastic://, or file:/.","If referencing a Ghidra server repository, use the ghidra:// protocol format so isServerRepositoryURL returns true.","Validate the URL string is well-formed before passing it to deriveBSimURL.","Check for typos in the scheme or missing '://' separator."],"exampleFix":"// before\nURL url = BSimClientFactory.deriveBSimURL(\"myhost:5432/bsimdb\"); // no protocol\n//\n// after\nURL url = BSimClientFactory.deriveBSimURL(\"postgresql://myhost:5432/bsimdb\");","handlingStrategy":"validation","validationCode":"URL test = new URI(urlString).toURL();\nString proto = test.getProtocol();\nboolean isBSim = Set.of(\"postgresql\", \"https\", \"elastic\", \"file\").contains(proto);\nboolean isGhidraRepo = GhidraURL.isServerRepositoryURL(test);\nif (!isBSim && !isGhidraRepo) {\n    // Inform user: URL must be a BSim protocol or a Ghidra server repository URL\n}","typeGuard":null,"tryCatchPattern":"try {\n    BSimClientFactory.deriveBSimURL(urlString);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Unable to infer BSim URL\")) {\n        // prompt user for a valid BSim or ghidra:// URL\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always include a protocol scheme in the URL string.","Use ghidra:// for Ghidra server repository URLs; use BSim protocols for direct DB connections.","Validate URL well-formedness before passing to deriveBSimURL.","Provide URL format examples in the input UI."],"tags":["bsim","url-parsing","url-derivation","configuration"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}