{"record":{"id":"b0a6205c35086f75","repo":"NationalSecurityAgency/ghidra","slug":"bsim-url-must-specify-exactly-1-path-element","errorCode":null,"errorMessage":"BSim URL must specify exactly 1 path element","messagePattern":"BSim URL must specify exactly 1 path element","errorType":"validation","errorClass":"MalformedURLException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java","lineNumber":61,"sourceCode":"\n\t/**\n\t * Validate BSim DB URL.\n\t * Acceptable protocols are  postgresql://  https://,  (or possibly http://) file:/\n\t * @param url BSim DB URL\n\t * @throws MalformedURLException if the URL string is not a support BSim DB URL\n\t */\n\tpublic static void checkBSimServerURL(URL url) throws MalformedURLException {\n\t\tString protocol = url.getProtocol();\n\t\tif (!protocol.equals(\"postgresql\") && !protocol.equals(\"https\") &&\n\t\t\t!protocol.equals(\"elastic\") && !protocol.equals(\"file\")) {\n\t\t\tthrow new MalformedURLException(\"Protocol not permissable for BSim URL\");\n\t\t}\n\t\tString path = url.getPath();\n\t\tif (path == null || path.length() == 0 || path.equals(\"/\")) {\n\t\t\tthrow new MalformedURLException(\"BSim URL missing DB name/path\");\n\t\t}\n\t\tif (!\"file\".equals(protocol) && path.indexOf('/', 1) >= 0) {\n\t\t\tthrow new MalformedURLException(\"BSim URL must specify exactly 1 path element\");\n\t\t}\n\t}\n\n\t/**\n\t * Construct the root URL to a specific BSim repository given a \"related\" URL.\n\t * The root URL will have an explicit protocol, a hostname + other mods (the authority), and 1 level of path\n\t *    this first level path indicates the particular repository being referenced on the host.\n\t * The \"related\" URL -url- can be an explicitly provided URL pointing to the BSim repository,\n\t *    possibly with additional path levels, which are simply stripped from the final root URL.\n\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)","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java#L43-L79","documentation":"checkBSimServerURL() enforces that for non-file protocols the URL path has exactly one path element (no '/' after position 1). If path.indexOf('/', 1) >= 0 it means there are nested path segments, which BSim doesn't allow for server-backed databases — the single path element IS the database name.","triggerScenarios":"Calling checkBSimServerURL(url) with a non-file protocol URL where the path contains a second '/'. E.g., 'postgresql://host/dbname/extra' or 'https://host/path/to/db'.","commonSituations":"User includes a sub-path (thinking BSim needs a full filesystem path); URL constructed by joining host + filesystem path with '/'; user provides a REST-style nested path; copy-paste of a URL from a different system that uses multi-level paths.","solutions":["Reduce the URL path to a single segment: 'postgresql://host/dbname' (remove everything after the first path element).","If you need to reference a file on disk, use the 'file' protocol which allows multi-level paths.","Review URL construction logic to ensure only the database name (not a filesystem path) is appended for server protocols."],"exampleFix":"// before\nString url = \"postgresql://myhost/bsim/v1/db\"; // multiple path elements\n//\n// after\nString url = \"postgresql://myhost/bsimdb\"; // single path element","handlingStrategy":"validation","validationCode":"String path = url.getPath();\nif (!\"file\".equals(url.getProtocol()) && path.indexOf('/', 1) >= 0) {\n    // Multiple path segments for a server protocol\n    throw new IllegalArgumentException(\n        \"Server protocol URLs must have exactly one path element (the database name). Use file:/ for multi-level paths.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    BSimClientFactory.checkBSimServerURL(url);\n} catch (MalformedURLException e) {\n    if (e.getMessage().contains(\"exactly 1 path element\")) {\n        // strip extra path segments, keep only the database name\n    } else {\n        throw e;\n    }\n}","preventionTips":["Use only the database name (single segment) for server protocol URLs.","Switch to file:/ protocol if you need multi-level filesystem paths.","Avoid joining host + filesystem path when constructing BSim server URLs."],"tags":["bsim","url-validation","path","configuration"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}