openai / openai/codex

[Notion connector] query_data_sources SQL returns query-shape-dependent stale row snapshots

Open
#42,686 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app bug tool-calls
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What version of the Codex App are you using?

ChatGPT/Codex Desktop: 26.831.21537 (build 7579)
Embedded Codex runtime: 0.152.1

What subscription do you have?

Not disclosed. The connected Notion workspace reports that fetch, query_data_sources, view queries, and update operations are available.

What platform are you using?

macOS 26.6.2 (build 25G83)
Apple Silicon / arm64

What issue are you seeing?

The Notion connector's query_data_sources SQL mode can return different versions of the same database row depending on the SQL query shape.

A private Notion database contains one canonical row whose live page property and page body both say Approved. The database's normal view also returns Approved, and its filtered Draft view excludes the row.

However, SQL initially returned an older Draft snapshot of the same page ID, including older text and relation values.

After re-saving the live Status property as Approved and waiting for propagation:

  • a targeted SQL query by unique ID returned the current Approved row;
  • the original targeted query also eventually returned the current row;
  • WHERE Status = 'Approved' AND <unique ID> returned the row;
  • WHERE Status = 'Draft' correctly excluded the row;
  • but a broad SQL scan still returned the same row as the older Draft snapshot;
  • SQL aggregate queries still counted the stale snapshot.

This is query-shape dependent within the same data source and observation window.

Reproduction outline
  1. Connect the official Notion app in Codex Desktop.
  2. Fetch a private Notion database and obtain its collection://... data-source URL.
  3. Choose one row that was previously Draft and is now Approved.
  4. Confirm through notion_fetch that the page property is Approved.
  5. Confirm through view-mode query_data_sources that the normal view returns Approved and the Draft-filtered view excludes the row.
  6. Run equivalent SQL queries against the same data source.

Sanitized query examples:

SELECT *
FROM "collection://REDACTED"
WHERE "Record ID" = ? OR "Title" = ?;
SELECT url, "Record ID", "Title", "Status"
FROM "collection://REDACTED"
WHERE "Status" = ? AND "Record ID" = ?;
-- params: ["Approved", 26]
SELECT url, "Record ID", "Title", "Status"
FROM "collection://REDACTED"
ORDER BY "Record ID";
SELECT "Status", COUNT(*) AS row_count
FROM "collection://REDACTED"
GROUP BY "Status";
Actual result

For the same canonical page ID:

Read path Result
Direct page fetch Approved, current content/relations
Database view mode Approved, current content/relations
Draft-filtered view Row absent
Targeted SQL by ID Approved, current content/relations
SQL WHERE Status='Approved' AND ID=? Row present as Approved
SQL WHERE Status='Draft' Row absent
Broad unfiltered SQL scan Same row appears as older Draft snapshot
SQL aggregate 56 Approved / 7 Draft / 2 In Review
View-mode rows, counted client-side 57 Approved / 6 Draft / 2 In Review

The broad SQL snapshot also contained older non-status field values, so this is not only a status-filter anomaly.

The database has 65 active rows. Duplicate checks found one active record with this ID/title, no archived duplicate, one data source, and one stable page ID across all reads.

Expected behavior

All SQL query shapes over one Notion data source should resolve a canonical page ID to the same current property values.

At minimum:

  1. targeted, filtered, broad-scan, and aggregate SQL queries must use the same snapshot/version;
  2. a row excluded by WHERE Status='Draft' must not simultaneously contribute to the Draft aggregate;
  3. view-mode and SQL-mode reads should converge after a successful property update;
  4. if results are intentionally cached, the response should expose freshness/snapshot metadata and use consistent invalidation across query shapes.
Impact

Automated governance and assessment workflows can misclassify approved records, produce incorrect catalogue totals, and make decisions from stale text or relations even though direct page reads and database views are current.

Because the response has no freshness or projection version metadata, an agent cannot reliably detect which SQL shape is stale without cross-checking every row through another API path.

Additional information

Observed on 2026-09-04.

One idempotent property write was attempted to refresh the projection. It improved some targeted SQL reads after a short propagation interval but did not repair broad scans or aggregates. No repeated toggling or destructive workaround was attempted.

Temporary safe workaround: use direct page fetches or view-mode database queries for governance-critical reads and compute totals from returned view rows.

Potentially related but not a duplicate: #34618 concerns query_data_sources being unavailable; in this report the tool is available and executes, but SQL projections are internally inconsistent.

All workspace names, page/database/data-source IDs, page titles, URLs, relation targets, user identities, and private content have been removed from this public report.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the discrepancy with the listed direct-fetch, view-mode, targeted SQL, broad-scan, and aggregate queries against one data source. Compare the page IDs, returned values, and counts across query shapes and inspect the connector implementation that handles these read paths; done means all SQL shapes resolve the same current snapshot or expose consistent freshness metadata.

Written by the indexing model from the issue text.

Assessment

Domain
api, backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.