feat: Ignore missing `include` targets (on fetch & query) with optional `ignoreIncludeErrors` flag.
Pull Request
- Report security issues confidentially.
- Any contribution is under this license.
- Link this pull request to an issue.
Issue
Closes: #9869
Approach
- Added an opt-in
ignoreIncludeErrorsboolean query option that flows from the routers through RestQuery, defaulting to the existing strict behaviour (throws Parse.Error.OBJECT_OBJECT_NOT_FOUND when included fields on Query/FetchWithInclude are no longer accessible). - When the
ignoreIncludeErrorsflag is set; Updateincludehydration with so unresolved pointers are left in place instead of throwing (current behavior) when the flag is set; arrays keep their original ordering and any missing entries stay as raw pointer JSON.- Edited the database controller to bypass the 101 error for nested FETCH/GET operations only when the option is enabled, while preserving all ACL/CLP enforcement.
- Added REST tests that cover both unreadable pointers and partially missing arrays to prove the relaxed behaviour.
Tasks
- [x] Add tests
- [x] Add changes to documentation (guides, repository pages, code comments)
Summary by CodeRabbit
-
New Features
- Added an optional ignoreIncludeErrors flag for GET/FIND requests to preserve unreadable or unresolved included pointers (including inside arrays) and return 200 instead of failing.
-
Behavior
- Default behavior unchanged: without the flag, requests may return 404/OBJECT_NOT_FOUND when includes canβt be hydrated.
-
Tests
- Added tests covering unreadable/unresolved include pointers and array scenarios with and without the flag.
π Thanks for opening this pull request!
π Walkthrough
Walkthrough
Adds a per-request ignoreIncludeErrors flag propagated from routers into RestQuery and DatabaseController.find; threads a preserveMissing option through pointer replacement to preserve unresolved/unreadable pointers during include resolution; tests added to validate behavior. No public API removals.
Changes
| Cohort / File(s) | Summary of Changes |
|---|---|
Tests: include error tolerancespec/rest.spec.js |
Adds tests for ignoreIncludeErrors: unreadable pointers preserved as Pointer objects when flag is true; arrays preserve unresolved pointers; 404 returned when include hydration fails without the flag. |
Routing / request parsingsrc/Routers/ClassesRouter.js |
Accepts ignoreIncludeErrors in GET query params and FIND bodies, coerces/validates to boolean, and includes it in the options passed to REST handling; updates allowed GET query keys. |
Query options surfacesrc/Adapters/Storage/StorageAdapter.js |
Adds ignoreIncludeErrors?: boolean to the QueryOptions type. |
Database get/find behaviorsrc/Controllers/DatabaseController.js |
Adds ignoreIncludeErrors to find options; when op is 'get' and permission/include filtering yields no query, returns [] instead of throwing OBJECT_NOT_FOUND if the flag is true. |
Include resolution and pointer replacementsrc/RestQuery.js |
Propagates ignoreIncludeErrors via preserveMissing; replacePointers now accepts an options param and preserves unresolved/unreadable pointers (including array elements) when requested; threads options through recursive calls. |
Sequence Diagram(s)
sequenceDiagram
autonumber
participant C as Client
participant R as ClassesRouter
participant Q as RestQuery
participant D as DatabaseController
participant S as StorageAdapter
Note over C,R: GET /classes/:Class/:id?include=...&ignoreIncludeErrors=true
C->>R: HTTP GET (include + ignoreIncludeErrors=true)
R->>Q: build RestQuery (ignoreIncludeErrors=true)
Q->>D: find(op='get', options.ignoreIncludeErrors=true)
D->>S: query for include targets
alt include targets unreadable/missing
S-->>D: no readable matches
D-->>Q: return [] (instead of OBJECT_NOT_FOUND due to flag)
else include targets found
S-->>D: matched records
D-->>Q: include records
end
Q->>Q: replacePointers(preserveMissing=true)
Note over Q: unresolved/unreadable pointers preserved as Pointer objects
Q-->>R: result with preserved pointers
R-->>C: 200 OK
sequenceDiagram
autonumber
participant C as Client
participant R as ClassesRouter
participant Q as RestQuery
participant D as DatabaseController
Note over C,R: GET with include, ignoreIncludeErrors not set
C->>R: HTTP GET (include)
R->>Q: build RestQuery (no ignoreIncludeErrors)
Q->>D: find(op='get', options.ignoreIncludeErrors=false)
alt include permission/filtering removes target
D-->>Q: throws OBJECT_NOT_FOUND
Q-->>R: propagate error
R-->>C: 404 OBJECT_NOT_FOUND
else include targets resolved
D-->>Q: include records
Q-->>R: hydrated object
R-->>C: 200 OK
end
Estimated code review effort
π― 3 (Moderate) | β±οΈ ~25 minutes
- Pay attention to:
- Correct propagation of
ignoreIncludeErrorsthrough REST/Router -> RestQuery -> DatabaseController -> StorageAdapter. - Behavior changes in DatabaseController.find when returning
[]vs throwing OBJECT_NOT_FOUND for op='get'. - replacePointers recursion and array handling when
preserveMissingis enabled. - Type change in QueryOptions and any TypeScript/flow impacts.
- Correct propagation of
Suggested reviewers
- Moumouls
Pre-merge checks and finishing touches
β Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title Check | β Passed | The PR title "feat: Ignore missing include targets (on fetch & query) with optional ignoreIncludeErrors flag" clearly and concisely summarizes the primary change: introducing an optional flag to gracefully handle missing include targets. The title is specific enough to convey the feature's purpose and directly reflects the main objective of the changeset across all modified files (StorageAdapter, DatabaseController, RestQuery, ClassesRouter, and tests). |
| Linked Issues Check | β Passed | The PR addresses the core requirements from issue #9869. The linked issue requests a backwards-compatible option to prevent include queries from failing when included pointers are deleted or unreadable, with the proposal suggesting modes including 'pointer' (return as raw pointer JSON). The implementation provides an opt-in ignoreIncludeErrors boolean flag that, when enabled, implements the 'pointer' mode by preserving unresolved pointers as raw pointer JSON instead of throwing errors, preserves array ordering with missing entries as pointers, maintains ACL/CLP enforcement, and defaults to the strict behavior (throwing errors), satisfying the primary objective of solving the root query failure problem while surfacing missing includes in a tolerant way. |
| Out of Scope Changes Check | β Passed | All code changes are directly related to implementing the ignoreIncludeErrors feature as described in issue #9869 and the PR objectives. The modifications span from storage adapters (QueryOptions type), database controller (error handling logic), REST query handling (preserveMissing pointer replacement), routing layer (parameter propagation), and corresponding test coverage. No extraneous changes such as refactoring, unrelated bug fixes, or feature modifications outside the scope of this feature are present in the changeset. |
| Description Check | β Passed | The PR description follows the repository template structure and includes all required sections: Issue (linked to #9869), Approach (explaining the feature implementation including the preserveMissing behavior and ACL/CLP enforcement), and Tasks (marking tests and documentation as completed). The description provides sufficient context about the implementation, including how unresolved pointers are preserved as raw pointer JSON and how arrays maintain their ordering. While some template sections like security checks are not explicitly addressed, the core required information is present and complete. |
| Docstring Coverage | β Passed | Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. |
β¨ Finishing touches
- [ ] π Generate docstrings
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
:white_check_mark: Snyk checks have passed. No issues have been found so far.
| Status | Scanner | Total (0) | ||||
|---|---|---|---|---|---|---|
| :white_check_mark: | Open Source Security | 0 | 0 | 0 | 0 | 0 issues |
:computer: Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.
Codecov Report
:x: Patch coverage is 94.44444% with 1 line in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 93.01%. Comparing base (b298ccc) to head (ccc9cad).
:warning: Report is 1 commits behind head on alpha.
| Files with missing lines | Patch % | Lines |
|---|---|---|
| src/Routers/ClassesRouter.js | 75.00% | 1 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## alpha #9872 +/- ##
==========================================
- Coverage 93.01% 93.01% -0.01%
==========================================
Files 187 187
Lines 15163 15176 +13
Branches 177 177
==========================================
+ Hits 14104 14116 +12
- Misses 1047 1048 +1
Partials 12 12
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
- :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.