When using the SQLITE_OPEN_URI "the filename can be interpreted as a URI". However, for it to be treated as a URI, it must be prefixed with file:, else it will be treated as a normal filename.
So you are trying to open a file named database.db?immutable=1, which obviously doesn't exist. Note that with SQLITE_OPEN_READONLY "if the database does not already exist, an error is returned". Therefore the simplest fix is simply to make the string be file:database.db?immutable=1.
However I suggest you stick to only one method of providing special options; use the SQLITE_OPEN_URI flag, and put all the other options into the URI, like so: file:database.db?mode=ro&immutable=1.
(I realise that not all combinations of options are possible using only a single method, but in your case it is, so I say stick to one and then you don't need to worry about the way different methods interact).
SQLite has extensive documentation, and you can read all about opening databases here.
SQLITE_OPEN_READONLYflag with theSQLITE_OPEN_URImode. I suggest trying just theREADONLYflag and passing the normal database name as the first argument. (I think you need to precede the db name withfile:anyway in URI mode). Alternatively, use only theURIflag, and then usefile:database.db?mode=ro&immutable=1.SQLITE_OPEN_URIenables URI filenames but non-uris still work: sqlite.org/c3ref/open.html "If URI filename interpretation is enabled, and the filename argument begins with "file:", then the filename is interpreted as a URI"database.db?immutable=1is not a non-URI, so it would need thefile:prefix.