Interesting; I didn't think to try it without the UNION. I suspected UNION ALL had something to do with triggering the problem, because plain UNION does not show the bad behavior, i.e. this returns both rows: SELECT *, sqlite_version() FROM ( SELECT NULL val FROM (SELECT 1) UNION SELECT 'missing' FROM (SELECT 1) ) LEFT JOIN (SELECT 1) ON val IS NULL;