400 HTTP error trying to access database from Apple Watch on iPhone when it's locked

23 views
Skip to first unread message

Brendan Duddridge

unread,
Jan 2, 2018, 3:31:03 AM1/2/18
to Couchbase Mobile
Hi,

Whenever I try to fetch from the CBL 1.4.1 database when my iPhone is locked via a message sent from my Apple Watch app, I get the following error in the device's console log:

Jan  1 22:18:22 iPhone-X Tap Forms[11762] <Notice>: Error opening Tap Forms database: Error Domain=CBLHTTP Code=400 "Invalid database/document/revision ID" UserInfo={NSLocalizedFailureReason=Invalid database/document/revision ID, NSLocalizedDescription=Invalid database/document/revision ID}


I have Data Protection on in my entitlements and configured to be using NSFileProtectionCompleteUntilFirstUserAuthentication

I also have it set to that in iTunes Connect for my App ID.

If the device is on then I can query the database and I get results.

Does anyone know how to get this to work? I'm using WatchOS 4.2 and the app doing the fetching from CBL is running on iOS 11.2.1.

P.S. I did read through the other threads about accessing data from an Apple Watch app, but it was inconclusive. I thought just using NSFileProtectionCompleteUntilFirstUserAuthentication for the Data Protection mode would suffice, but it doesn't appear to be so.



Thanks,

Brendan

Jens Alfke

unread,
Jan 2, 2018, 12:59:53 PM1/2/18
to mobile-c...@googlegroups.com

On Jan 2, 2018, at 12:31 AM, Brendan Duddridge <bren...@gmail.com> wrote:

Jan  1 22:18:22 iPhone-X Tap Forms[11762] <Notice>: Error opening Tap Forms database: Error Domain=CBLHTTP Code=400 "Invalid database/document/revision ID" UserInfo={NSLocalizedFailureReason=Invalid database/document/revision ID, NSLocalizedDescription=Invalid database/document/revision ID}

The error message refers to opening the database, but your email implies the database is already open. Do you know which API call this error is returned from? And is anything being logged before this error?

This isn’t the error I’d expect when the filesystem is locked. In 1.4 and 1.4.1, Pasin and I added code to detect those filesystem/SQLite errors and return appropriate CBL errors (I think it’s 401.)

I thought just using NSFileProtectionCompleteUntilFirstUserAuthentication for the Data Protection mode would suffice, but it doesn't appear to be so.

I would think so, too. It kind of looks like something else is going wrong.

—Jens

Jens Alfke — Mobile Architect — Couchbase, Inc.

Brendan Duddridge

unread,
Jan 3, 2018, 1:45:28 AM1/3/18
to Couchbase Mobile

The error message refers to opening the database, but your email implies the database is already open. Do you know which API call this error is returned from? And is anything being logged before this error?

This isn’t the error I’d expect when the filesystem is locked. In 1.4 and 1.4.1, Pasin and I added code to detect those filesystem/SQLite errors and return appropriate CBL errors (I think it’s 401.)

This error happened before the application was launched. It was launched via the sendMessage call on the Apple Watch app.

So the error was from the following code:

NSError *error = nil;

CBLDatabaseOptions *options = [[CBLDatabaseOptions alloc] init];

// options.storageType = kCBLForestDBStorage;

// options.storageType = kCBLSQLiteStorage;

options.encryptionKey = self.encryptionKey;

options.create = YES;

BOOL databaseExists = [self.couchManager databaseExistsNamed:dbName];

self.couchDatabase = [self.couchManager openDatabaseNamed:dbName

 withOptions:options

error:&error];


if (error && error.code == 401) {

// database file is encrypted. Ask for a key.

self.isDatabaseEncrypted = YES;

self.documentIsLocked = YES;

} else if (error || !self.couchDatabase) {

NSLog(@"Error opening Tap Forms database: %@", error);

So it's that last NSLog that's being triggered to display that 400 error message.


BUT, when I have the app opened and access the data from the watch, everything works ok. About 20 or so seconds after the phone is locked, even if the app was running, I start getting no data back from the app. So it seems after a little while the database can no longer be accessed.

 

Jens Alfke

unread,
Jan 3, 2018, 11:14:32 AM1/3/18
to mobile-c...@googlegroups.com
OK, so the error is being returned from -openDatabaseNamed:. Which certainly seems to imply that the filesystem is inaccessible. Except that NSFileProtectionCompleteUntilFirstUserAuthentication is documented as:

The file is stored in an encrypted format on disk and cannot be accessed until after the device has booted. After the user unlocks the device for the first time, your app can access the file and continue to access it even if the user subsequently locks the device.

One possibility: you may be seeing an error where there is none, since your error handling logic is incorrect:

if (error && error.code == 401) {

// ...trimmed...

else if (error || !self.couchDatabase) {
NSLog(@"Error opening Tap Forms database: %@", error);

In Cocoa error handling, failure is signaled by the return value being nil (or NO or whatever), not by the `error` result being non-nil. In fact the `error` result is undefined unless the return value indicates an error. (This mistake is easier to make nowadays with ARC; in the old days, an NSError* local variable would be initialized to garbage, meaning that you’d likely crash if you accessed it when it hadn’t been set.)

The code should be something like:

if (!self.couchDatabase) {
if (error.code == 401) {
 …
} else {
NSLog(@"Error opening Tap Forms database: %@", error);
}
}

Try that and see if it helps.

—Jens

Brendan Duddridge

unread,
Jan 3, 2018, 1:47:10 PM1/3/18
to Couchbase Mobile
Thanks for the tip Jens.

I did initialize my NSError variable prior to executing that code:


NSError *error = nil;


But I've just reworked it as you suggested, so I'll see if that solves the problem.


Thanks!


Brendan


Reply all
Reply to author
Forward
0 new messages