{"record":{"id":"547d0d97aabcd51f","repo":"OpenRefine/OpenRefine","slug":"paths-to-sqlite-databases-are-not-allowed-to-conta","errorCode":null,"errorMessage":"Paths to SQLite databases are not allowed to contain '?'","messagePattern":"Paths to SQLite databases are not allowed to contain '\\?'","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/database/src/com/google/refine/extension/database/sqlite/SQLiteConnectionManager.java","lineNumber":74,"sourceCode":"    /**\n     * Create a new instance of this connection manager.\n     *\n     * @return an instance of the manager\n     */\n    public static SQLiteConnectionManager getInstance() {\n        if (instance == null) {\n            if (logger.isDebugEnabled()) {\n                logger.debug(\"::Creating new SQLite ConnectionManager ::\");\n            }\n            instance = new SQLiteConnectionManager();\n        }\n        return instance;\n    }\n\n    public static String getDatabaseUrl(DatabaseConfiguration dbConfig) {\n        String dbPath = dbConfig.getDatabaseName();\n        if (dbPath.contains(\"?\")) {\n            throw new IllegalArgumentException(\"Paths to SQLite databases are not allowed to contain '?'\");\n        }\n        if (dbPath.startsWith(\"//\") || dbPath.startsWith(\"\\\\\\\\\") || dbPath.startsWith(\"\\\\/\") || dbPath.startsWith(\"/\\\\\")) {\n            throw new IllegalArgumentException(\"File path starts with illegal prefix; only local files are accepted.\");\n        }\n        if (!new File(dbPath).isFile()) {\n            throw new IllegalArgumentException(\"File could not be read: \" + dbPath);\n        }\n        try {\n            URI uri = new URI(\n                    \"jdbc:\" + dbConfig.getDatabaseType().toLowerCase(),\n                    dbPath + \"?open_mode=1&limit_attached=0\", // open_mode=1 means read-only\n                    null);\n            return uri.toASCIIString();\n        } catch (URISyntaxException e) {\n            throw new IllegalArgumentException(e);\n        }\n    }\n","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/OpenRefine/OpenRefine/blob/a946177e049f3b0644261661db36cbb0c81ccf8a/extensions/database/src/com/google/refine/extension/database/sqlite/SQLiteConnectionManager.java#L56-L92","documentation":"SQLiteConnectionManager.getDatabaseUrl builds the SQLite JDBC URL from the configured database path and rejects paths containing '?'. A '?' would start the JDBC connection-parameter section of the URL, letting the path inject options (like open_mode) that would break the read-only hardening, so it is refused up front.","triggerScenarios":"Creating a SQLite connection whose DatabaseConfiguration.databaseName contains a literal '?' character, e.g. a URL-style path \"jdbc:sqlite:/tmp/db?mode=ro\" pasted into the filename field.","commonSituations":"Users pasting full JDBC URLs or web URLs into the SQLite database path field; config files holding parameterized paths; copy-paste mistakes from other SQLite tooling.","solutions":["Strip any '?query' portion from the path and supply only the local file path (e.g. /data/mydb.sqlite).","Set read-only or other SQLite options via the extension's supported configuration, not by appending URL parameters.","Validate the configured path in your form/config before invoking the connection."],"exampleFix":"// before\ndbConfig.setDatabaseName(\"jdbc:sqlite:/tmp/testdb.sqlite?mode=ro\");\n// after\ndbConfig.setDatabaseName(\"/tmp/testdb.sqlite\");","handlingStrategy":"validation","validationCode":"public static void validateSqlitePath(String path) {\n  if (path == null || path.contains(\"?\")) throw new IllegalArgumentException(\"SQLite path must not contain '?'\");\n}\nvalidateSqlitePath(dbPath); dbConfig.setDatabaseName(dbPath);","typeGuard":"boolean isValidSqlitePath(String p) { return p != null && !p.contains(\"?\"); }","tryCatchPattern":"try { service.openConnection(dbConfig); } catch (IllegalArgumentException e) { /* strip query part and retry */ }","preventionTips":["Store plain local file paths in the databaseName field","Strip any '?options' suffix users paste from JDBC URLs","Configure read-only via the extension, not URL parameters"],"tags":["sqlite","input-validation","jdbc","security"],"backgroundTag":"invalid-argument-value","analyzedSha":"a946177e049f3b0644261661db36cbb0c81ccf8a","analyzedAt":"2026-09-08T10:21:27.735Z","contentChangedAt":"2026-09-08T10:21:27.735Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}